Incorporate Issue 130313.5, Add support for Fortran assumed-rank arrays.
authorAdrian Prantl <aprantl@apple.com>
Mon, 23 Sep 2013 23:17:49 +0000 (16:17 -0700)
committerAdrian Prantl <aprantl@apple.com>
Mon, 23 Sep 2013 23:17:49 +0000 (16:17 -0700)
dwarf5/latexdoc/attributesbytag.tex
dwarf5/latexdoc/changesummary.tex
dwarf5/latexdoc/datarepresentation.tex
dwarf5/latexdoc/dwarfnamecmds.tex
dwarf5/latexdoc/examples.tex
dwarf5/latexdoc/generaldescription.tex
dwarf5/latexdoc/introduction.tex
dwarf5/latexdoc/typeentries.tex

index 451b0c6..34e6d15 100644 (file)
@@ -281,6 +281,30 @@ means include all three of the
 &\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} \\
index afd0d1c..2a0fcb2 100644 (file)
@@ -14,6 +14,7 @@ This change summary is included only in draft versions of this document.
 \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)        \\
@@ -26,4 +27,4 @@ This change summary is included only in draft versions of this document.
                        & 110404.1 (DW\_TAG\_member typos) \\
 
 \end{tabular}
-\end{abstract}
\ No newline at end of file
+\end{abstract}
index 0bad0dc..9ada421 100644 (file)
@@ -564,6 +564,7 @@ Table \refersec{tab:tagencodings}.
 \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}
@@ -1215,6 +1216,8 @@ Table \refersec{tab:attributeformencodings}.
                \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}  \\
 
index c140835..3765039 100644 (file)
@@ -12,6 +12,7 @@
 \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}}
@@ -47,6 +48,7 @@
 %
 \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}}
index 01adf51..744a095 100644 (file)
@@ -676,6 +676,164 @@ illustrated in Figure \refersec{fig:FortranmultidimensionalcoarrayDWARFdescripti
 \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}
index e9f8905..3f642d9 100644 (file)
@@ -45,6 +45,7 @@ described in Chapters 3, 4 and 5.
 \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},
@@ -334,6 +335,8 @@ actually declared in the source}{objects or types that are not actually declared
 &\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}
@@ -2263,9 +2266,10 @@ rules of the applicable programming language.
 \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}
index 89c0098..f1a17f0 100644 (file)
@@ -137,6 +137,11 @@ The following is a list of the major changes made to the DWARF Debugging Informa
 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:
index 407d151..661e335 100644 (file)
@@ -561,6 +561,7 @@ source syntax) in other languages.}
 
 \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}
@@ -660,6 +661,15 @@ first, next to leftmost second, and so on).
 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}, 
@@ -1948,6 +1958,11 @@ whose value is a null\dash terminated
 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
@@ -2189,7 +2204,7 @@ a
 (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}
@@ -2287,6 +2302,42 @@ pointer assignment.}
 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}