&\livelink{chap:DWATfriend}{DW\_AT\_friend} \\
&\livelink{chap:DWATsibling}{DW\_AT\_sibling} \\
+\hline
+% Please keep in synch with DW_TAG_subrange_type.
+\livelink{chap:DWTAGgenericsubrange}{DW\_TAG\_generic\_subrange}
+&\livelink{chap:DECL}{DECL} \\
+&\livelink{chap:DWATabstractorigin}{DW\_AT\_abstract\_origin} \\
+&\livelink{chap:DWATaccessibility}{DW\_AT\_accessibility} \\
+&\livelink{chap:DWATallocated}{DW\_AT\_allocated} \\
+&\livelink{chap:DWATassociated}{DW\_AT\_associated} \\
+&\livelink{chap:DWATbitsize}{DW\_AT\_bit\_size} \\
+&\livelink{chap:DWATbitstride}{DW\_AT\_bit\_stride} \\
+&\livelink{chap:DWATbytesize}{DW\_AT\_byte\_size} \\
+&\livelink{chap:DWATbytestride}{DW\_AT\_byte\_stride} \\
+&\livelink{chap:DWATcount}{DW\_AT\_count} \\
+&\livelink{chap:DWATdatalocation}{DW\_AT\_data\_location} \\
+&\livelink{chap:DWATdeclaration}{DW\_AT\_declaration} \\
+&\livelink{chap:DWATdescription}{DW\_AT\_description} \\
+&\livelink{chap:DWATlowerbound}{DW\_AT\_lower\_bound} \\
+&\livelink{chap:DWATname}{DW\_AT\_name} \\
+&\livelink{chap:DWATsibling}{DW\_AT\_sibling} \\
+&\livelink{chap:DWATthreadsscaled}{DW\_AT\_threads\_scaled} \\
+&\livelink{chap:DWATtype}{DW\_AT\_type} \\*
+&\livelink{chap:DWATupperbound}{DW\_AT\_upper\_bound} \\*
+&\livelink{chap:DWATvisibility}{DW\_AT\_visibility} \\
+
\hline
\livelink{chap:DWTAGimporteddeclaration}{DW\_TAG\_imported\_declaration}
&\livelink{chap:DECL}{DECL} \\
\vspace{1cm}
\begin{tabular}{ll}
\textbf{Date} & \textbf{Issue Incorported or Other Change} \\ \hline \\
+9/23/2013 & 130313.5 (Fortran assumed-rank arrays)\\
6/22/2013 & 100805.1 (value of reference), 100816.1 (remove .debug\_types), \\
& 101014.1, 101111.1, 120218.1 (Go, Modula-3 and Haskell), \\
& 110803.1 (tls), 110926.1 (DW\_OP\_callx), 121212.1 (type unit) \\
& 110404.1 (DW\_TAG\_member typos) \\
\end{tabular}
-\end{abstract}
\ No newline at end of file
+\end{abstract}
\livelink{chap:DWTAGrvaluereferencetype}{DW\_TAG\_rvalue\_reference\_type} &0x42 \\
\livelink{chap:DWTAGtemplatealias}{DW\_TAG\_template\_alias} &0x43 \\
\livelink{chap:DWTAGcoarraytype}{DW\_TAG\_coarray\_type} &0x44 \\
+\livelink{chap:DWTAGgenericsubrange}{DW\_TAG\_generic\_subrange} &0x45 \\
\livelink{chap:DWXXXlohiuser}{DW\_TAG\_lo\_user}&0x4080 \\
\livelink{chap:DWXXXlohiuser}{DW\_TAG\_hi\_user}&\xffff \\
\end{longtable}
\livelink{chap:classconstant}{constant}\addtoindexx{string length attribute!size of length} \\
\livelink{chap:DWATstringlengthbytesize}{DW\_AT\_string\_length\_byte\_size} \ddag&0x70&
\livelink{chap:classconstant}{constant}\addtoindexx{string length attribute!size of length} \\
+ \livelink{chap:DWATrank}{DW\_AT\_rank} \ddag&0x71&
+ \livelink{chap:DWATrank}{constant, exprloc}\addtoindexx{rank attribute!encoding} \\
\livelink{chap:DWXXXlohiuser}{DW\_AT\_lo\_user}&0x2000 & --- \addtoindexx{low user attribute encoding} \\
\livelink{chap:DWXXXlohiuser}{DW\_AT\_hi\_user}&\xiiifff& --- \addtoindexx{high user attribute encoding} \\
\newcommand{\DWATname}{\addtoindex{DW\_AT\_name}}
\newcommand{\DWATordering}{\addtoindex{DW\_AT\_ordering}}
\newcommand{\DWATranges}[1][]{\addtoindex{DW\_AT\_ranges}}
+\newcommand{\DWATrank}[1][]{\addtoindex{DW\_AT\_rank}}
\newcommand{\DWATsibling}{\addtoindexx{DW\_AT\_sibling}}
\newcommand{\DWATstmtlist}[1][]{\addtoindex{DW\_AT\_stmt\_list}}
\newcommand{\DWATstringlength}{\addtoindex{DW\_AT\_string\_length}}
%
\newcommand{\DWTAGarraytype}{\addtoindex{DW\_TAG\_array\_type}}
\newcommand{\DWTAGcoarraytype}{\addtoindex{DW\_TAG\_coarray\_type}}
+\newcommand{\DWTAGgenericsubrange}{\addtoindex{DW\_TAG\_generic\_subrange}}
\newcommand{\DWTAGmember}{\addtoindex{DW\_TAG\_member}}
\newcommand{\DWTAGsubrangetype}{\addtoindex{DW\_TAG\_subrange\_type}}
\newcommand{\DWTAGvariable}{\addtoindex{DW\_TAG\_variable}}
\label{fig:FortranmultidimensionalcoarrayDWARFdescription}
\end{figure}
+
+\clearpage
+\subsection{Fortran 2008 Assumed-rank Array Example}
+\label{app:assumedrankexample}
+Consider the example in Figure~\ref{fig:assumedrankdecl}, which shows
+an assumed-rank array in Fortran~2008 with
+supplement~29113:\footnote{Technical Specification ISO/IEC TS
+ 29113:2012 \emph{Further Interoperability of Fortran with C}}
+
+\begin{figure}[!h]
+\begin{lstlisting}[language={[95]Fortran}]
+ subroutine foo(x)
+ real :: x(..)
+
+ ! x has n dimensions
+
+ end subroutine
+\end{lstlisting}
+\caption{Declaration of a Fortran 2008 assumed-rank array}
+\label{fig:assumedrankdecl}
+\end{figure}
+
+Let's assume the Fortran compiler used an array descriptor that looks
+like the one shown in Figure~\ref{fig:arraydesc}.
+
+\begin{figure}[!h]
+\begin{lstlisting}[language=C]
+ struct array_descriptor {
+ void *base_addr;
+ int rank;
+ struct dim dims[];
+ }
+
+ struct dim {
+ int lower_bound;
+ int upper_bound;
+ int stride;
+ int flags;
+ }
+\end{lstlisting}
+\caption{One of many possible layouts for an array descriptor}
+\label{fig:arraydesc}
+\end{figure}
+
+The DWARF type for the array \emph{x} can be described as shown in
+Figure~\ref{fig:assumedrankdwarf}.
+
+\begin{figure}[!h]
+\begin{minipage}[t]{\linewidth}
+\centering
+Abbreviation Table: \dotdebugabbrev{}
+\begin{framed}
+\scriptsize
+\begin{alltt}
+10\$: \DWTAGarraytype
+ \livelink{chap:DWATtype}{DW\_AT\_type}(reference to real)
+ \livelink{chap:DWATrank}{DW\_AT\_rank}(expression=
+ \livelink{chap:DWOPpushobjectaddress}{DW\_OP\_push\_object\_address}
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<offset of rank in descriptor>
+ \livelink{chap:DWOPplus}{DW\_OP\_plus}
+ \livelink{chap:DWOPderef}{DW\_OP\_deref})
+ \livelink{chap:DWATdatalocation}{DW\_AT\_data\_location}(expression=
+ \livelink{chap:DWOPpushobjectaddress}{DW\_OP\_push\_object\_address}
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<offset of data in descriptor>
+ \livelink{chap:DWOPplus}{DW\_OP\_plus}
+ \livelink{chap:DWOPderef}{DW\_OP\_deref})
+11\$: \DWTAGgenericsubrange
+ \livelink{chap:DWATtype}{DW\_AT\_type}(reference to integer)
+ \livelink{chap:DWATlowerbound}{DW\_AT\_lower\_bound}(expression=
+ ! Looks up the lower bound of dimension i.
+
+ ! Operation ! Stack effect
+ ! (implicit) ! i
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<byte size of struct dim> ! i sizeof(dim)
+ \livelink{chap:DWOPmult}{DW\_OP\_mult} ! dim[i]
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<offset of dim in descriptor> ! dim[i] offset
+ \livelink{chap:DWOPplus}{DW\_OP\_plus} ! dim[i]+offset
+ \livelink{chap:DWOPpushobjectaddress}{DW\_OP\_push\_object\_address} ! dim[i]+offset objptr
+ \livelink{chap:DWOPplus}{DW\_OP\_plus} ! objptr.dim[i]
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<offset of lowerbound in dim> ! objptr.dim[i] offset
+ \livelink{chap:DWOPplus}{DW\_OP\_plus} ! objptr.dim[i].lowerbound
+ \livelink{chap:DWOPderef}{DW\_OP\_deref}) ! *objptr.dim[i].lowerbound
+ \livelink{chap:DWATupperbound}{DW\_AT\_upper\_bound}(expression=
+ ! Looks up the upper bound of dimension i.
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<byte size of dim>
+ \livelink{chap:DWOPmult}{DW\_OP\_mult}
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<offset of dim in descriptor>
+ \livelink{chap:DWOPplus}{DW\_OP\_plus}
+ \livelink{chap:DWOPpushobjectaddress}{DW\_OP\_push\_object\_address}
+ \livelink{chap:DWOPplus}{DW\_OP\_plus}
+ \livelink{chap:DWOPlit}{DW\_OP\_lit}<offset of upperbound in dim>
+ \livelink{chap:DWOPplus}{DW\_OP\_plus}
+ \livelink{chap:DWOPderef}{DW\_OP\_deref})
+ \livelink{chap:DWATbytestride}{DW\_AT\_byte\_stride}(expression=
+ ! Looks up the byte stride of dimension i.
+ ...
+ ! (analogous to DW\_AT\_upper\_bound)
+ )
+\end{alltt}
+\end{framed}
+\end{minipage}
+\caption{Sample DWARF for the array descriptor in Figure~\ref{fig:arraydesc}}
+\label{fig:assumedrankdwarf}
+\end{figure}
+
+The layout of the array descriptor is not specified by the Fortran
+standard unless the array is explicitly marked as C-interoperable. To
+get the bounds of an assumed-rank array, the expressions in the
+\DWTAGgenericsubrange{} type need to be evaluated for each of the
+\DWATrank{} dimensions as shown the pseudocode in
+Figure~\ref{fig:assumedrankdwarfparser}.
+
+\begin{figure}[!h]
+\begin{lstlisting}[language=C]
+ typedef struct {
+ int lower, upper, stride;
+ } dims_t;
+
+ typedef struct {
+ int rank;
+ struct dims_t *dims;
+ } array_t;
+
+ array_t get_dynamic_array_dims(DW_TAG_array a) {
+ array_t result;
+
+ // Evaluate the DW_AT_rank expression to get the number of dimensions.
+ dwarf_stack_t stack;
+ dwarf_eval(stack, a.rank_expr);
+ result.rank = dwarf_pop(stack);
+ result.dims = new dims_t[rank];
+
+ // Iterate over all dimensions and find their bounds.
+ for (int i = 0; i < result.rank; i++) {
+ // Evaluate the generic subrange's DW_AT_lower expression for dimension i.
+ dwarf_push(stack, i);
+ assert( stack.size == 1 );
+ dwarf_eval(stack, a.generic_subrange.lower_expr);
+ result.dims[i].lower = dwarf_pop(stack);
+ assert( stack.size == 0 );
+
+ dwarf_push(stack, i);
+ dwarf_eval(stack, a.generic_subrange.upper_expr);
+ result.dims[i].upper = dwarf_pop(stack);
+
+ dwarf_push(stack, i);
+ dwarf_eval(stack, a.generic_subrange.byte_stride_expr);
+ result.dims[i].stride = dwarf_pop(stack);
+ }
+ return result;
+ }
+\end{lstlisting}
+\caption{How to interpret the DWARF from Figure~\ref{fig:assumedrankdwarf}}
+\label{fig:assumedrankdwarfparser}
+\end{figure}
+
+
+
\clearpage
\subsection{Ada Example}
\label{app:adaexample}
\livelink{chap:DWTAGconsttype}{DW\_TAG\_const\_type},
\livelink{chap:DWTAGconstant}{DW\_TAG\_constant},
\livelink{chap:DWTAGdwarfprocedure}{DW\_TAG\_dwarf\_procedure},
+\livelink{chap:DWTAGgenericsubrange}{DW\_TAG\_generic\_subrange},
\livelink{chap:DWTAGentrypoint}{DW\_TAG\_entry\_point},
\livelink{chap:DWTAGenumerationtype}{DW\_TAG\_enumeration\_type},
\livelink{chap:DWTAGenumerator}{DW\_TAG\_enumerator},
&\livelinki{chap:DWATpurepurepropertyofasubroutine}{Pure property of a subroutine}{pure property of a subroutine} \\
\livetarg{chap:DWATranges}{DW\_AT\_ranges}
&\livelinki{chap:DWATrangesnoncontiguousrangeofcodeaddresses}{Non-contiguous range of code addresses}{non-contiguous range of code addresses} \\
+\livetarg{chap:DWATrank}{DW\_AT\_rank}
+&\livelinki{chap:DWATrank}{Dynamic number of array dimensions}{dynamic number of array dimensions} \\
\livetarg{chap:DWATrecursive}{DW\_AT\_recursive}
&\livelinki{chap:DWATrecursiverecursivepropertyofasubroutine}{Recursive property of a subroutine}{recursive property of a subroutine} \\
\livetarg{chap:DWATreturnaddr}{DW\_AT\_return\_addr}
\livelink{chap:DWATcount}{DW\_AT\_count},
\livelink{chap:DWATlowerbound}{DW\_AT\_lower\_bound},
\livelink{chap:DWATbytestride}{DW\_AT\_byte\_stride},
-\livelink{chap:DWATbitstride}{DW\_AT\_bit\_stride},
-\livelink{chap:DWATupperbound}{DW\_AT\_upper\_bound} (and
-possibly others).}
+\livelink{chap:DWATbitstride}{DW\_AT\_bit\_stride},
+\livelink{chap:DWATupperbound}{DW\_AT\_upper\_bound},
+\livelink{chap:DWATrank}{DW\_AT\_rank},
+ (and possibly others).}
\needlines{6}
\section{Entity Descriptions}
Format since Version 4 was published. The list is not meant to be exhaustive.
\begin{itemize}
\item TBD...
+\item Added a new attribute, \DWATrank{}, to describe the dimensionality of
+an array.
+\item Added a new tag, \DWTAGgenericsubrange{}, to describe the
+bounds of Fortran assumed-rank arrays.
+
\end{itemize}
DWARF Version 5 is compatible with DWARF Version 4 except as follows:
\section{Array Type Entries}
\label{chap:arraytypeentries}
+\label{chap:DWTAGgenericsubrange}
\textit{Many languages share the concept of an \doublequote{array,} which is
\addtoindexx{array type entry}
be represented by a debugging information entry for a
multidimensional array.}
+\hypertarget{chap:DWTAGgenericsubrange}
+Alternatively, the array dimensions can also be described with the
+\DWTAGgenericsubrange, which contains only a single, generic
+expression describing each of the attributes. If \DWTAGgenericsubrange
+is used, the number dimensions must be stored in the
+\livelink{chap:DWATrank}{DW\_AT\_rank} attribute. See also Section
+\ref{chap:DWATrank}, Dynamic Type Properties: Array Rank.
+
+
\needlines{5}
Other attributes especially applicable to arrays are
\livelink{chap:DWATallocated}{DW\_AT\_allocated},
string containing the subrange type name as it appears in
the source program.
+The tag
+\livelink{chap:DWTAGgenericsubrange}{DW\_TAG\_generic\_subrange} is
+used to describe arrays with a dynamic rank. See Section
+\ref{chap:DWTAGgenericsubrange}.
+
The subrange entry may have
\addtoindexx{type attribute}
a \livelink{chap:DWATtype}{DW\_AT\_type} attribute to describe
(see Section \refersec{chap:staticanddynamicvaluesofattributes})
is the amount of storage need to hold a value of the file type.
-\section{Dynamic Type Properties}
+\subsection{Dynamic Type Properties}
\label{chap:dynamictypeproperties}
\subsection{Data Location}
\label{chap:datalocation}
arrays,
see Appendix \refersec{app:aggregateexamples}.}
+\subsection{Array Rank}
+\label{chap:DWATrank}
+\textit{The Fortran language supports ``assumed-rank arrays''. The
+ rank (the number of dimensions) of an assumed-rank array is unknown
+ at compile time. The Fortran runtime stores the rank in the array
+ descriptor metadata.}
+
+The presence of \DWATrank{} indicates that an array's rank
+(dimensionality) is dynamic, and therefore unknown at compile
+time. \DWATrank{} contains an expression that can be evaluated to look
+up the dynamic rank from the array descriptor.
+
+The dimensions of an array with dynamic rank are described using the
+\DWTAGgenericsubrange{} tag. The \DWTAGgenericsubrange{} tag is the
+dynamic rank array equivalent of
+\livelink{chap:DWTAGsubrangetype}{DW\_TAG\_subrange\_type}. The
+difference is that a \DWTAGgenericsubrange{} contains generic
+lower/upper bound and stride expressions that need to be evaluated for
+each dimension: Before any expression contained in a
+\DWTAGgenericsubrange{} can be evaluated, the dimension for which the
+expression should be evaluated needs to be pushed onto the stack. The
+expression will use it to find the offset of the respective field in
+the array descriptor metadata.
+
+\textit{The Fortran compiler is free to choose any layout for the
+ array descriptor. In particular, the upper and lower bounds and
+ stride values do not need to be bundled into a structure or record,
+ but could be laid end to end in the containing descriptor, pointed
+ to by the descriptor, or even allocated independently of the
+ descriptor.}
+
+Dimensions are enumerated $0$ to $\mathit{rank}-1$ in a left-to-right
+fashion.
+
+\textit{For an example in Fortran 2008, see
+ Section~\ref{app:assumedrankexample}.}
\section{Template Alias Entries}