<div dir="ltr"><div>Ben,</div><div><br></div><div>I am puzzling over your vector types proposal as well as the Tye proposal you cite. My impression is that they are hard to distinguish.</div><div>The Tye proposal turns CPU vector types into base types while your proposal keeps them distinct, but then you add this additional class of types to the base types of operands in all of the types where it matters, in particular DW_OP_regval_type, DW_OP_deref_type and DW_OP_xderef_type. In both cases you end up being able to push and pop complete register contents to/from the DWARF stack. You mention a possible maximum size of 2048 bytes *currently*, but that seems likely to continue to grow over time. <br></div><div><br></div><div>Is it really important to have all of the vector register contents on the DWARF stack at one time? What can be done to operate on such</div><div>a stack value? Seems like there needs to be at least a way to DW_OP_reinterpret such a value to/from a sequence of values of the element type on the stack. (If nothing else, what is the corresponding element order? IE, does the DEBUG stack grow up or down?😊)<br></div><div><br></div><div>What if we start with the proposal where CPU vector types are not base types, then instead add operators such as DW_OP_regval_idx_type,</div><div>DW_OP_deref_idx_type and DW_OP_xderef_idx_type, each of which adds one additional parameter, an index, to push or pop a single element of the vector array. Then a debugger can treat such arrays like all other arrays; operations generally iterate over the elements in the obvious way.</div><div><br></div><div>Among other things, this alternative seems like it would have few if any problems with SVE or RVV.</div><div></div><div><br></div><div>At a higher level of discourse, I think it would be unusual for a source program vector (one-dimensional array) to ever be directly allocated in a vector register and spend its entire lifetime there, right? Thus, these CPU vector types should generally also have a DW_AT_artificial attribute, I think. They might not even have a name but if they did it would be some kind of pseudo-name (VR@@1 or whatever). Is it expected that users will need to name these registers directly as part of debugging or is the goal to make the compiled code use of vector registers as transparent as its use of general registers? <br></div><div><br></div><div>As I say, I am just puzzling... <br></div><div><br></div><div>Ron<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 24, 2023 at 2:20 PM Ben Woodard via Dwarf-discuss <<a href="mailto:dwarf-discuss@lists.dwarfstd.org" target="_blank">dwarf-discuss@lists.dwarfstd.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  

    
  
  <div>
    <p>I was working on this before the change of administration. <br>
    </p>
    <p>Vector types have been around for a very long time and compilers
      use them but are not handled in the DWARF standard right on
      DWARF5. I think that this was basically something that was
      overlooked and no one filed an issue to get it addressed in the
      standard. <br>
    </p>
    <p>There are two different proposals about how to handle them and I
      believe that the committee should discuss the two options and then
      decide a course of action.</p>
    <p>At the bottom of this email is my proposal. I will admit that in
      its current state it is a work in progress. My original intent was
      to simply codify the existing behavior as implemented by GCC and
      LLVM (and probably other compilers) moving it from a vendor
      attribute to something that was in the standard. However, at the
      time I was working with Tony Tye and the people at AMD on one of
      their proposals toto better support GPUs and this involved a lot
      of work on the DWARF stack and the operations done within them.
      This led me to realize a problem with my initial proposal and that
      was that it didn't consider the impacts on the DWARF stack
      operations. I reworked my proposal to include changes in that area
      of the standard. Essentially it adds language to all operations
      that were limited to a base type now would also work on a vector
      type of a base type. Tony raised an objection to this and argued
      that handling vector types on the DWARF stack was not necessary. I
      have not put in the time to really come up with a counter example
      to that assertion. He may be correct. I'm personally not sure. No
      current compiler that I am aware of actually generates DWARF that
      makes use of the DWARF stack with vector types. My intuition is
      that there may be a case related to scatter gather where it could
      be useful to make use vector registers on the DWARF stack.</p>
    <p>Tony Tye has a different proposal.
<a href="https://github.com/t-tye/dwarf-locations/blob/main/014-vector-base-types.txt" target="_blank">https://github.com/t-tye/dwarf-locations/blob/main/014-vector-base-types.txt</a>
    </p>
    <p>His proposal basically amounts to make vector types base types. I
      can't say that I disagree with that overall approach. My concerns
      are:</p>
    <ol>
      <li>It breaks with existing behavior.</li>
      <li>It would greatly increase the number of base types for a
        platform. I think that it would be the combinatorial expansion
        of all the available encodings and the architecture's available
        vector lengths.<br>
      </li>
      <li>There is an interaction between the Platform Specific ABI and
        the base types for an architecture. I'm not sure but I think
        that the PS ABI for the various architectures might need
        revision given this change. Given how many architectures there
        are<br>
      </li>
      <li>It would immediately allow the large vector registers on the
        DWARF stack and I fear that some DWARF stack implementations
        which are currently based on a platform's size of an INT would
        break. Some architecture's vector registers could be as large as
        2048b.</li>
      <li>I don't know how it will deal with hardware implementation
        variable vector lengths like ARM's SVE or RISC-V RVV. Just for
        reference for people who may not know this is a quick intro to
        SVE
<a href="https://www.stonybrook.edu/commcms/ookami/support/_docs/3%20-%20Intro%20to%20SVE.pdf" target="_blank">https://www.stonybrook.edu/commcms/ookami/support/_docs/3%20-%20Intro%20to%20SVE.pdf</a><br>
      </li>
    </ol>
    <p>Anyway, my biggest concern is that in the DWARF6 process vector
      register types get standardized. In general I have come to respect
      Tony as a very thoughtful architect, so I would not be upset if
      his proposal were accepted over mine. I would just like to make
      sure that the concerns that I've pointed out above are considered.<br>
    </p>
    <p>----------------------------------<br>
    </p>
    <p><font face="monospace">Vector registers<br>
        <br>
        It has been the long standing existing practice to treat
        hardware<br>
        vector registers as arrays of a fundamental base type. To
        deliniate<br>
        these hardware register arrays from arrays in the language
        source they<br>
        have been given the DW_AT_GNU_vector attribute. This proposal
        simply<br>
        standardizes the existing behavior.<br>
        <br>
        In Section 2.2 Attribute Types, DW_AT_vector and<br>
        DW_AT_variable_vector_width shall be added to Table 2.2<br>
        <br>
           
        --------------------------------------------------------------------<br>
            DW_AT_vector                | A hardware vector register<br>
            DW_AT_variable_vector_width | Array bound for hardware<br>
                                        | implementation defined vector
        register<br>
                                        | width<br>
           
        --------------------------------------------------------------------<br>
        <br>
        The hyperlink in the "Identifies or Specifies" column shall
        point to<br>
        the paragraph added to Section 5.5 below for DW_AT_vector and
        the<br>
        paragraph added to Section 5.13 below for<br>
        DW_AT_variable_vector_width.<br>
        <br>
        In Section 2.5.1.2 Register values replace the description of<br>
        DW_OP_regval_type with the following:<br>
        <br>
           
        --------------------------------------------------------------------<br>
            The DW_OP_regval_type operation provides the contents of a
        given<br>
            register interpreted as a value of a given type. The first
        operand<br>
            is an unsigned LEB128 number, which identifies a register
        whose<br>
            contents is to be pushed onto the stack. The second operand
        is an<br>
            unsigned LEB128 number that represents the offset of a
        debugging<br>
            information entry in the current compilation unit, which
        must be a<br>
            DW_TAG_base_type entry that provides the type of the value<br>
            contained in the specified register or it must be an<br>
            DW_TAG_array_type with a DW_AT_vector attribute.<br>
        <br>
            [non-normative] A DW_TAG_array_type with a DW_AT_vector
        attribute<br>
            is the way that a vector register is specified and can be<br>
            considered a base type for the architecture.<br>
           
        --------------------------------------------------------------------<br>
        <br>
        In Section 2.5.1.3 Stack Operations replace the description of<br>
        DW_OP_deref_type with the following:<br>
        <br>
           
        --------------------------------------------------------------------<br>
            The DW_OP_deref_type operation behaves like the
        DW_OP_deref_size<br>
            operation: it pops the top stack entry and treats it as an<br>
            address. The popped value must have an integral type. The
        value<br>
            retrieved from that address is pushed together with a type<br>
            identifier. In the DW_OP_deref_type operation, the size in
        bytes<br>
            of the data retrieved from the dereferenced address is
        specified<br>
            by the first operand. This operand is a 1-byte unsigned
        integral<br>
            constant whose value which is the same as the size of the
        type<br>
            referenced by the second operand. The second operand is an<br>
            unsigned LEB128 integer that represents the offset of a
        debugging<br>
            information entry in the current compilation unit that
        provides<br>
            the type of the data pushed. This entry must be either a<br>
            DW_TAG_base_type entry or a DW_TAG_array_type entry with a<br>
            DW_AT_vector attribute.<br>
           
        --------------------------------------------------------------------<br>
        <br>
        Replace the description of DW_OP_xderef_type with the following:<br>
        <br>
           
        --------------------------------------------------------------------<br>
            The DW_OP_xderef_type operation behaves like the
        DW_OP_xderef_size<br>
            operation: it pops the top two stack entries, treats them as
        an<br>
            address and an address space identifier, and pushes the
        value<br>
            retrieved. In the DW_OP_xderef_type operation, the size in
        bytes<br>
            of the data retrieved from the dereferenced address is
        specified<br>
            by the first operand. This operand is a 1-byte unsigned
        integral<br>
            constant whose value value is the same as the size of the
        type<br>
            referenced by the second operand. The second operand is an<br>
            unsigned LEB128 integer that represents the offset of a
        debugging<br>
            information entry in the current compilation unit that
        provides<br>
            the type of the data pushed. This entry must be a
        DW_TAG_base_type<br>
            entry or a DW_TAG_array_type entry with a DW_AT_vector
        attribute.<br>
           
        --------------------------------------------------------------------<br>
        <br>
        In Section 5.5 Array Type Entries, replace first paragraph of<br>
        non-normative text with:<br>
        <br>
           
        --------------------------------------------------------------------<br>
            [non-normative] Many languages share the concept of an
        “array,”<br>
            which is a table of components of identical type.
        Furthermore,<br>
            many architectures contain vector registers which mirror the<br>
            language concept of an array.<br>
           
        --------------------------------------------------------------------<br>
        <br>
        Insert the following paragraph between the first paragraph of<br>
        normative text describing DW_TAG_array_type and the second
        paragraph<br>
        dealing with multidimensional ordering.<br>
        <br>
           
        --------------------------------------------------------------------<br>
            An array type that refers to a hardware vector register,
        shall be<br>
            denoted with DW_AT_vector. The the width of the register
        shall be<br>
            specified as an array dimension and the type contained
        within the<br>
            register must be a DW_TAG_base_type entry.<br>
           
        --------------------------------------------------------------------<br>
        <br>
        In Section 5.13 Subrange Type Entries insert the following
        paragraph<br>
        between the paragraph defining DW_AT_threads_scaled and the one<br>
        defining DW_AT_lower_bound and DW_AT_upper_bound.<br>
        <br>
           
        --------------------------------------------------------------------<br>
            The subrange entry may have a DW_AT_variable_vector_width<br>
            attribute, which is a flag. If present, this attriburte
        indicates<br>
            that the width of a vector is defined by the hardware<br>
            implementation of the target. The actual width of the vector<br>
            registers can be determined at runtime but is unknown at
        compile<br>
            time.<br>
           
        --------------------------------------------------------------------<br>
        <br>
      </font></p>
    <p><br>
    </p>
  </div>

-- <br>
Dwarf-discuss mailing list<br>
<a href="mailto:Dwarf-discuss@lists.dwarfstd.org" target="_blank">Dwarf-discuss@lists.dwarfstd.org</a><br>
<a href="https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss" rel="noreferrer" target="_blank">https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss</a><br>
</blockquote></div>