Changes in / [03606ce:06601401]


Ignore:
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • doc/papers/llheap/Makefile

    r03606ce r06601401  
    1717
    1818FIGURES = ${addsuffix .tex, \
     19AddressSpace \
    1920AllocatorComponents \
    2021AllocatedObject \
     
    5657
    5758PICTURES = ${addsuffix .pstex, \
    58 AddressSpace \
    5959MultipleHeapsOwnershipStorage \
    6060PrivatePublicHeaps \
  • doc/papers/llheap/Paper.tex

    r03606ce r06601401  
    8282xleftmargin=\parindentlnth,                             % indent code to paragraph indentation
    8383escapechar=\$,                                                  % LaTeX escape in CFA code
    84 mathescape=false,                                               % disable LaTeX math escape in CFA code $...$
     84%mathescape=true,                                               % LaTeX math escape in CFA code $...$
    8585keepspaces=true,                                                %
    8686showstringspaces=false,                                 % do not show spaces with cup
     
    9090numberstyle=\footnotesize\sf,                   % numbering style
    9191moredelim=**[is][\color{red}]{@}{@},
    92 % replace/adjust listing characters that look bad in sanserif
    93 literate=
    94 %  {-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1
    95   {-}{\raisebox{-1pt}{\ttfamily-}}1
    96   {^}{\raisebox{0.6ex}{\(\scriptstyle\land\,\)}}1
    97   {~}{\raisebox{0.3ex}{\(\scriptstyle\sim\,\)}}1
    98   {'}{\ttfamily'\hspace*{-0.4ex}}1
    99   {`}{\ttfamily\upshape\hspace*{-0.3ex}`}1
    100   {<-}{$\leftarrow$}2
    101   {=>}{$\Rightarrow$}2
    102 %  {->}{\raisebox{-1pt}{\texttt{-}}\kern-0.1ex\textgreater}2,
    10392}% lstset
    10493
     
    10695\lstdefinelanguage{CFA}[ANSI]{C}{
    10796        morekeywords={
    108                 _Alignas, _Alignof, __alignof, __alignof__, and, asm, __asm, __asm__, _Atomic, __attribute, __attribute__,
    109                 __auto_type, basetypeof, _Bool, catch, catchResume, choose, coerce, _Complex, __complex, __complex__, __const, __const__,
    110                 coroutine, _Decimal32, _Decimal64, _Decimal128, disable, enable, exception, __extension__, fallthrough, fallthru, finally, fixup,
    111                 __float80, float80, __float128, float128, _Float16, _Float32, _Float32x, _Float64, _Float64x, _Float128, _Float128x,
    112                 forall, fortran, generator, _Generic, _Imaginary, __imag, __imag__, inline, __inline, __inline__, int128, __int128, __int128_t,
    113                 __label__, monitor, mutex, _Noreturn, __builtin_offsetof, one_t, or, recover, report, restrict, __restrict, __restrict__,
    114                 __signed, __signed__, _Static_assert, suspend, thread, __thread, _Thread_local, throw, throwResume, timeout, trait, try,
    115                 typeof, __typeof, __typeof__, typeid, __uint128_t, __builtin_va_arg, __builtin_va_list, virtual, __volatile, __volatile__,
    116                 vtable, waitfor, waituntil, when, with, zero_t,
    117     },
     97                _Alignas, _Alignof, __alignof, __alignof__, asm, __asm, __asm__, __attribute, __attribute__,
     98                auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
     99                coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally,
     100                __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__,
     101                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
     102                otype, restrict, resume, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, thread,
     103                _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,
     104                virtual, __volatile, __volatile__, waitfor, when, with, zero_t},
    118105        moredirectives={defined,include_next},
     106        % replace/adjust listing characters that look bad in sanserif
     107        literate={-}{\makebox[1ex][c]{\raisebox{0.5ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
     108                {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
     109                {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
     110                {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textrm{\textgreater}}}2,
    119111}
    120112
    121113% uC++ programming language, based on ANSI C++
    122 \lstdefinelanguage{uC++}[GNU]{C++}{
     114\lstdefinelanguage{uC++}[ANSI]{C++}{
    123115        morekeywords={
    124                 _Accept, _AcceptReturn, _AcceptWait, _Actor, _At, _Catch, _CatchResume, _CorActor, _Cormonitor, _Coroutine,
    125                 _Disable, _Else, _Enable, _Event, _Exception, _Finally, _Monitor, _Mutex, _Nomutex, _PeriodicTask, _RealTimeTask,
    126                 _Resume, _ResumeTop, _Select, _SporadicTask, _Task, _Timeout, _When, _With, _Throw},
     116                _Accept, _AcceptReturn, _AcceptWait, _Actor, _At, _CatchResume, _Cormonitor, _Coroutine, _Disable,
     117                _Else, _Enable, _Event, _Finally, _Monitor, _Mutex, _Nomutex, _PeriodicTask, _RealTimeTask,
     118                _Resume, _Select, _SporadicTask, _Task, _Timeout, _When, _With, _Throw},
    127119}
    128120
     
    141133        morestring=[b]",
    142134        morestring=[s]{`}{`},
     135        % replace/adjust listing characters that look bad in sanserif
     136        literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
     137                {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
     138                {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
     139                {<-}{\makebox[2ex][c]{\textrm{\textless}\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}}2,
    143140}
    144141
    145 \lstnewenvironment{cfa}[1][]{\lstset{language=CFA,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}{}
    146 \lstnewenvironment{C++}[1][]{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}{}
    147 \lstnewenvironment{uC++}[1][]{\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}{}
    148 \lstnewenvironment{Go}[1][]{\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}{}
    149 \lstnewenvironment{python}[1][]{\lstset{language=python,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}{}
    150 \lstnewenvironment{java}[1][]{\lstset{language=java,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}{}
     142\lstnewenvironment{cfa}[1][]
     143{\lstset{language=CFA,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}
     144{}
     145\lstnewenvironment{C++}[1][]                            % use C++ style
     146{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}
     147{}
     148\lstnewenvironment{uC++}[1][]
     149{\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}
     150{}
     151\lstnewenvironment{Go}[1][]
     152{\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}
     153{}
     154\lstnewenvironment{python}[1][]
     155{\lstset{language=python,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}
     156{}
     157\lstnewenvironment{java}[1][]
     158{\lstset{language=java,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}}
     159{}
    151160
    152161% inline code @...@
     
    184193
    185194\author[1]{Mubeen Zulfiqar}
     195\author[1]{Peter A. Buhr*}
     196\author[1]{Thierry Delisle}
    186197\author[1]{Ayelet Wasik}
    187 \author[1]{Peter A. Buhr*}
    188 \author[2]{Bryan Chan}
    189198\authormark{ZULFIQAR \textsc{et al.}}
    190199
    191200\address[1]{\orgdiv{Cheriton School of Computer Science}, \orgname{University of Waterloo}, \orgaddress{\state{Waterloo, ON}, \country{Canada}}}
    192 \address[2]{\orgdiv{Huawei Compiler Lab}, \orgname{Huawei}, \orgaddress{\state{Markham, ON}, \country{Canada}}}
    193201
    194202\corres{*Peter A. Buhr, Cheriton School of Computer Science, University of Waterloo, 200 University Avenue West, Waterloo, ON N2L 3G1, Canada. \email{pabuhr{\char`\@}uwaterloo.ca}}
     
    196204% \fundingInfo{Natural Sciences and Engineering Research Council of Canada}
    197205
    198 \abstract[Summary]{%
    199 A new C-based concurrent memory-allocator is presented, called llheap (low latency).
     206\abstract[Summary]{
     207A new C-based concurrent memory-allocator is presented, called llheap.
    200208It can be used standalone in C/\CC applications with multiple kernel threads, or embedded into high-performance user-threading programming languages.
    201209llheap extends the feature set of existing C allocation by remembering zero-filled (\lstinline{calloc}) and aligned properties (\lstinline{memalign}) in an allocation.
    202210These properties can be queried, allowing programmers to write safer programs by preserving these properties in future allocations.
    203 As well, \lstinline{realloc} preserves these properties when adjusting storage size, again increasing future allocation safety.
    204 llheap also extends the C allocation API with \lstinline{aalloc}, \lstinline{amemalign}, \lstinline{cmemalign}, \lstinline{resize}, and extended \lstinline{realloc}, providing orthogonal access to allocation features;
    205 hence, programmers do have to code missing combinations.
    206 The llheap allocator also provides a contention-free statistics gathering mode, and a debugging mode for dynamically checking allocation pre/post conditions and invariants.
    207 These modes are invaluable for understanding and debugging a program's dynamic allocation behaviour, with low enough cost to be used in production code.
    208 The llheap API is further extended with the \CFA advanced type-system, providing a single type-safe allocation routine using named arguments, increasing safety and simplifying usage.
    209 Finally, performance results across a number of benchmarks show llheap is competitive with the best memory allocators.
    210 }% abstract
    211 
     211As well, \lstinline{realloc} preserves these properties when enlarging storage requests, again increasing future allocation safety.
     212llheap also extends the C allocation API with \lstinline{resize}, extended \lstinline{realloc}, \lstinline{aalloc}, \lstinline{amemalign}, and \lstinline{cmemalign} providing orthongoal ac, so programmers do not make mistakes writing theses useful allocation operations.
     213It is competitive with the best current memory allocators,
     214The ability to use \CFA's advanced type-system (and possibly \CC's too) to combine advanced memory operations into one allocation routine using named arguments shows how far the allocation API can be pushed, which increases safety and greatly simplifies programmer's use of dynamic allocation.
     215 low-latency
     216 without a performance loss
     217The llheap allocator also provides comprehensive statistics for all allocation operations, which are invaluable in understanding and debugging a program's dynamic behaviour.
     218As well, llheap provides a debugging mode where allocations are checked with internal pre/post conditions and invariants. It is extremely useful, especially for students.
     219% No other memory allocator examined in the work provides such comprehensive statistics gathering.
    212220% While not as powerful as the \lstinline{valgrind} interpreter, a large number of allocations mistakes are detected.
     221% Finally, contention-free statistics gathering and debugging have a low enough cost to be used in production code.
     222%
    213223% A micro-benchmark test-suite is started for comparing allocators, rather than relying on a suite of arbitrary programs. It has been an interesting challenge.
    214224% These micro-benchmarks have adjustment knobs to simulate allocation patterns hard-coded into arbitrary test programs.
    215225% Existing memory allocators, glibc, dlmalloc, hoard, jemalloc, ptmalloc3, rpmalloc, tbmalloc, and the new allocator llheap are all compared using the new micro-benchmark test-suite.
    216 
    217 \keywords{memory allocation, (user-level) concurrency, type-safety, statistics, debugging, high performance}
     226}% aabstract
     227
     228\keywords{C \CFA (Cforall) coroutine concurrency generator monitor parallelism runtime thread}
    218229
    219230
     
    226237\section{Introduction}
    227238
    228 Memory management services a series of program allocation/deallocation requests and attempts to satisfy them from a variable-sized block of memory, while minimizing total memory usage.
    229 A general-purpose dynamic-allocation algorithm cannot anticipate allocation requests so its time and space performance is rarely optimal.
    230 However, allocators take advantage of regular allocation patterns in typical programs to produce excellent results, both in time and space (similar to LRU paging).
    231 Allocators use a number of similar techniques, but each optimizes specific allocation patterns.
    232 Nevertheless, allocators are a series of compromises, occasionally with some static or dynamic tuning parameters to optimize specific program-request patterns.
     239Memory management takes a sequence of program generated allocation/deallocation requests and attempts to satisfy them within a fixed-sized block of memory while minimizing the total amount of memory used.
     240A general-purpose dynamic-allocation algorithm cannot anticipate future allocation requests so its output is rarely optimal.
     241However, memory allocators do take advantage of regularities in allocation patterns for typical programs to produce excellent results, both in time and space (similar to LRU paging).
     242In general, allocators use a number of similar techniques, each optimizing specific allocation patterns.
     243Nevertheless, memory allocators are a series of compromises, occasionally with some static or dynamic tuning parameters to optimize specific program-request patterns.
    233244
    234245
     
    236247\label{s:MemoryStructure}
    237248
    238 Figure~\ref{f:ProgramAddressSpace} shows the typical layout of a program's address space (high to low) divided into a number of zones, with free memory surrounding the dynamic code/data~\cite{memlayout}.
     249Figure~\ref{f:ProgramAddressSpace} shows the typical layout of a program's address space divided into the following zones (right to left): static code/data, dynamic allocation, dynamic code/data, and stack, with free memory surrounding the dynamic code/data~\cite{memlayout}.
    239250Static code and data are placed into memory at load time from the executable and are fixed-sized at runtime.
     251Dynamic-allocation memory starts empty and grows/shrinks as the program dynamically creates/deletes variables with independent lifetime.
     252The programming-language's runtime manages this area, where management complexity is a function of the mechanism for deleting variables.
    240253Dynamic code/data memory is managed by the dynamic loader for libraries loaded at runtime, which is complex especially in a multi-threaded program~\cite{Huang06}.
    241254However, changes to the dynamic code/data space are typically infrequent, many occurring at program startup, and are largely outside of a program's control.
    242255Stack memory is managed by the program call/return-mechanism using a LIFO technique, which works well for sequential programs.
    243256For stackful coroutines and user threads, a new stack is commonly created in the dynamic-allocation memory.
    244 The dynamic-allocation memory is often a contiguous area (can be memory mapped as multiple areas), which starts empty and grows/shrinks as the program creates/deletes variables with independent lifetime.
    245 The programming-language's runtime manages this area, where management complexity is a function of the mechanism for deleting variables.
    246257This work focuses solely on management of the dynamic-allocation memory.
    247258
    248259\begin{figure}
    249260\centering
    250 \input{AddressSpace.pstex_t}
     261\input{AddressSpace}
    251262\vspace{-5pt}
    252263\caption{Program Address Space Divided into Zones}
     
    258269\label{s:DynamicMemoryManagement}
    259270
    260 Modern programming languages manage dynamic memory in different ways.
     271Modern programming languages manage dynamic-allocation memory in different ways.
    261272Some languages, such as Lisp~\cite{CommonLisp}, Java~\cite{Java}, Haskell~\cite{Haskell}, Go~\cite{Go}, provide explicit allocation but \emph{implicit} deallocation of data through garbage collection~\cite{Wilson92}.
    262273In general, garbage collection supports memory compaction, where dynamic (live) data is moved during runtime to better utilize space.
    263 However, moving data requires finding and updating pointers to it to reflect the new data locations.
     274However, moving data requires finding pointers to it and updating them to reflect new data locations.
    264275Programming languages such as C~\cite{C}, \CC~\cite{C++}, and Rust~\cite{Rust} provide the programmer with explicit allocation \emph{and} deallocation of data.
    265276These languages cannot find and subsequently move live data because pointers can be created to any storage zone, including internal components of allocated objects, and may contain temporary invalid values generated by pointer arithmetic.
    266277Attempts have been made to perform quasi garbage collection in C/\CC~\cite{Boehm88}, but it is a compromise.
    267 This work only examines dynamic management with \emph{explicit} deallocation.
     278This work only examines dynamic memory-management with \emph{explicit} deallocation.
    268279While garbage collection and compaction are not part this work, many of the results are applicable to the allocation phase in any memory-management approach.
    269280
    270 Most programs use a general-purpose allocator, usually the one provided by the programming-language's runtime.
    271 In certain languages, programmers can write specialize allocators for specific needs.
    272 C and \CC allow easy replacement of the default memory allocator through a standard API.
     281Most programs use a general-purpose allocator, often the one provided implicitly by the programming-language's runtime.
     282When this allocator proves inadequate, programmers often write specialize allocators for specific needs.
     283C and \CC allow easy replacement of the default memory allocator with an alternative specialized or general-purpose memory-allocator.
    273284Jikes RVM MMTk~\cite{MMTk} provides a similar generalization for the Java virtual machine.
    274 As well, new languages support concurrency (kernel and/or user threading), which must be safely handled by the allocator.
    275 Hence, several alternative allocators exist for C/\CC with the goal of scaling in a multi-threaded program~\cite{Berger00,mtmalloc,streamflow,tcmalloc}.
     285However, high-performance memory-allocators for kernel and user multi-threaded programs are still being designed and improved.
     286For this reason, several alternative general-purpose allocators have been written for C/\CC with the goal of scaling in a multi-threaded program~\cite{Berger00,mtmalloc,streamflow,tcmalloc}.
    276287This work examines the design of high-performance allocators for use by kernel and user multi-threaded applications written in C/\CC.
    277288
     
    283294\begin{enumerate}[leftmargin=*,itemsep=0pt]
    284295\item
    285 Implementation of a new stand-alone concurrent low-latency memory-allocator ($\approx$1,200 lines of code) for C/\CC programs using kernel threads (1:1 threading), and specialized versions for the concurrent languages \uC~\cite{uC++} and \CFA~\cite{Moss18,Delisle21} using user-level threads running on multiple kernel threads (M:N threading).
    286 
    287 \item
    288 Extend the standard C heap functionality by preserving with each allocation its request size, the amount allocated, whether it is zero fill, and its alignment.
     296Implementation of a new stand-alone concurrent low-latency memory-allocator ($\approx$1,200 lines of code) for C/\CC programs using kernel threads (1:1 threading), and specialized versions of the allocator for the programming languages \uC~\cite{uC++} and \CFA~\cite{Moss18,Delisle21} using user-level threads running on multiple kernel threads (M:N threading).
     297
     298\item
     299Extend the standard C heap functionality by preserving with each allocation: its request size plus the amount allocated, whether an allocation is zero fill and/or allocation alignment.
    289300
    290301\item
    291302Use the preserved zero fill and alignment as \emph{sticky} properties for @realloc@ to zero-fill and align when storage is extended or copied.
    292 Without this extension, it is unsafe to @realloc@ storage these allocations if the properties are not preserved when copying.
    293 This silent problem is unintuitive to programmers and difficult to locate because it is transient.
    294 
    295 \item
    296 Provide additional heap operations to make allocation properties orthogonally accessible.
    297 \begin{itemize}[topsep=2pt,itemsep=2pt,parsep=0pt]
     303Without this extension, it is unsafe to @realloc@ storage initially allocated with zero-fill/alignment as these properties are not preserved when copying.
     304This silent generation of a problem is unintuitive to programmers and difficult to locate because it is transient.
     305
     306\item
     307Provide additional heap operations to complete programmer expectation with respect to accessing different allocation properties.
     308\begin{itemize}[topsep=3pt,itemsep=2pt,parsep=0pt]
     309\item
     310@resize( oaddr, size )@ re-purpose an old allocation for a new type \emph{without} preserving fill or alignment.
     311\item
     312@resize( oaddr, alignment, size )@ re-purpose an old allocation with new alignment but \emph{without} preserving fill.
     313\item
     314@realloc( oaddr, alignment, size )@ same as @realloc@ but adding or changing alignment.
    298315\item
    299316@aalloc( dim, elemSize )@ same as @calloc@ except memory is \emph{not} zero filled.
     
    302319\item
    303320@cmemalign( alignment, dim, elemSize )@ same as @calloc@ with memory alignment.
    304 \item
    305 @resize( oaddr, size )@ re-purpose an old allocation for a new type \emph{without} preserving fill or alignment.
    306 \item
    307 @resize( oaddr, alignment, size )@ re-purpose an old allocation with new alignment but \emph{without} preserving fill.
    308 \item
    309 @realloc( oaddr, alignment, size )@ same as @realloc@ but adding or changing alignment.
    310321\end{itemize}
     322
     323\item
     324Provide additional heap wrapper functions in \CFA creating a more usable set of allocation operations and properties.
    311325
    312326\item
     
    314328\begin{itemize}[topsep=3pt,itemsep=2pt,parsep=0pt]
    315329\item
    316 @malloc_alignment( addr )@ returns the alignment of the allocation.
     330@malloc_alignment( addr )@ returns the alignment of the allocation pointed-to by @addr@.
    317331If the allocation is not aligned or @addr@ is @NULL@, the minimal alignment is returned.
    318332\item
    319 @malloc_zero_fill( addr )@ returns a boolean result indicating if the memory is allocated with zero fill, e.g., by @calloc@/@cmemalign@.
    320 \item
    321 @malloc_size( addr )@ returns the size of the memory allocation.
    322 \item
    323 @malloc_usable_size( addr )@ returns the usable (total) size of the memory, i.e., the bin size containing the allocation, where @malloc_size( addr )@ $\le$ @malloc_usable_size( addr )@.
     333@malloc_zero_fill( addr )@ returns a boolean result indicating if the memory pointed-to by @addr@ is allocated with zero fill, e.g., by @calloc@/@cmemalign@.
     334\item
     335@malloc_size( addr )@ returns the size of the memory allocation pointed-to by @addr@.
     336\item
     337@malloc_usable_size( addr )@ returns the usable (total) size of the memory pointed-to by @addr@, i.e., the bin size containing the allocation, where @malloc_size( addr )@ $\le$ @malloc_usable_size( addr )@.
    324338\end{itemize}
    325339
    326340\item
    327 Provide optional extensive, fast, and contention-free allocation statistics to understand allocation behaviour, accessed by:
     341Provide complete, fast, and contention-free allocation statistics to help understand allocation behaviour:
    328342\begin{itemize}[topsep=3pt,itemsep=2pt,parsep=0pt]
    329343\item
    330 @malloc_stats()@ print memory-allocation statistics on the file-descriptor set by @malloc_stats_fd@ (default @stderr@).
    331 \item
    332 @malloc_info( options, stream )@ print memory-allocation statistics as an XML string on the specified file-descriptor set by @malloc_stats_fd@ (default @stderr@).
    333 \item
    334 @malloc_stats_fd( fd )@ set file-descriptor number for printing memory-allocation statistics (default @stderr@).
     344@malloc_stats()@ print memory-allocation statistics on the file-descriptor set by @malloc_stats_fd@.
     345\item
     346@malloc_info( options, stream )@ print memory-allocation statistics as an XML string on the specified file-descriptor set by @malloc_stats_fd@.
     347\item
     348@malloc_stats_fd( fd )@ set file-descriptor number for printing memory-allocation statistics (default @STDERR_FILENO@).
    335349This file descriptor is used implicitly by @malloc_stats@ and @malloc_info@.
    336350\end{itemize}
     
    341355\item
    342356Build 8 different versions of the allocator: static or dynamic linking, with or without statistics or debugging.
    343 A program may link to any of these 8 versions of the allocator often without recompilation (@LD_PRELOAD@).
    344 
    345 \item
    346 Provide additional heap wrapper functions in \CFA creating a more usable set of allocation operations and properties.
     357A program may link to any of these 8 versions of the allocator often without recompilation.
    347358
    348359\item
     
    354365\section{Background}
    355366
    356 The following is a quick overview of allocator design options that affect memory usage and performance (see~\cite{Zulfiqar22} for more details).
    357 Dynamic acquires and releases obtain storage for a program variable, called an \newterm{object}, through calls such as @malloc@/@new@ and @free@/@delete@ in C/\CC.
     367The following discussion is a quick overview of the moving-pieces that affect the design of a memory allocator and its performance.
     368Dynamic acquires and releases obtain storage for a program variable, called an \newterm{object}, through calls such as @malloc@ and @free@ in C, and @new@ and @delete@ in \CC.
     369Space for each allocated object comes from the dynamic-allocation zone.
     370
    358371A \newterm{memory allocator} contains a complex data-structure and code that manages the layout of objects in the dynamic-allocation zone.
    359372The management goals are to make allocation/deallocation operations as fast as possible while densely packing objects to make efficient use of memory.
    360 Since objects in C/\CC cannot be moved to aid the packing process, only adjacent free storage can be \newterm{coalesced} into larger free areas.
     373Objects in C/\CC cannot be moved to aid the packing process, only adjacent free storage can be \newterm{coalesced} into larger free areas.
    361374The allocator grows or shrinks the dynamic-allocation zone to obtain storage for objects and reduce memory usage via operating-system calls, such as @mmap@ or @sbrk@ in UNIX.
    362375
     
    370383The \newterm{storage data} is composed of allocated and freed objects, and \newterm{reserved memory}.
    371384Allocated objects (light grey) are variable sized, and are allocated and maintained by the program;
    372 \ie only the program knows the location of allocated storage.
    373 Freed objects (white) represent memory deallocated by the program, which are linked into one or more lists facilitating location of new allocations.
     385\ie only the program knows the location of allocated storage not the memory allocator.
     386Freed objects (white) represent memory deallocated by the program, which are linked into one or more lists facilitating easy location of new allocations.
    374387Reserved memory (dark grey) is one or more blocks of memory obtained from the \newterm{operating system} (OS) but not yet allocated to the program;
    375388if there are multiple reserved blocks, they are also chained together.
     
    388401An object may be preceded by padding to ensure proper alignment.
    389402Some algorithms quantize allocation requests, resulting in additional space after an object less than the quantized value.
     403% The buckets are often organized as an array of ascending bucket sizes for fast searching, \eg binary search, and the array is stored in the heap management-area, where each bucket is a top point to the freed objects of that size.
    390404When padding and spacing are necessary, neither can be used to satisfy a future allocation request while the current allocation exists.
    391405
     
    393407Often the free list is chained internally so it does not consume additional storage, \ie the link fields are placed at known locations in the unused memory blocks.
    394408For internal chaining, the amount of management data for a free node defines the minimum allocation size, \eg if 16 bytes are needed for a free-list node, allocation requests less than 16 bytes are rounded up.
    395 Often the minimum storage alignment and free-node size are the same.
    396409The information in an allocated or freed object is overwritten when it transitions from allocated to freed and vice-versa by new program data and/or management information.
    397410
     
    407420\label{s:SingleThreadedMemoryAllocator}
    408421
    409 In a sequential (single threaded) program, the program thread performs all allocation operations and concurrency issues do not exist.
    410 However, interrupts logically introduce concurrency, if the signal handler performs allocation/deallocation (serially reusable problem~\cite{SeriallyReusable}).
    411 In general, the primary issues in a single-threaded allocator are fragmentation and locality.
     422A single-threaded memory-allocator does not run any threads itself, but is used by a single-threaded program.
     423Because the memory allocator is only executed by a single thread, concurrency issues do not exist.
     424The primary issues in designing a single-threaded memory-allocator are fragmentation and locality.
     425
    412426
    413427\subsubsection{Fragmentation}
    414428\label{s:Fragmentation}
    415429
    416 Fragmentation is memory requested from the OS but not used allocated objects in by the program.
    417 Figure~\ref{f:InternalExternalFragmentation} shows fragmentation is divided into two forms: \emph{internal} or \emph{external}.
     430Fragmentation is memory requested from the OS but not used by the program;
     431hence, allocated objects are not fragmentation.
     432Figure~\ref{f:InternalExternalFragmentation} shows fragmentation is divided into two forms: internal or external.
    418433
    419434\begin{figure}
     
    424439\end{figure}
    425440
    426 \newterm{Internal fragmentation} is unaccessible allocated memory, such as headers, trailers, padding, and spacing around an allocated object.
    427 Internal fragmentation is problematic when management space becomes a significant proportion of an allocated object, \eg for objects $<$16 bytes, memory usage doubles.
    428 An allocator strives to keep internal management information to a minimum.
    429 
    430 \newterm{External fragmentation} is memory not allocated in the program~\cite{Wilson95,Lim98,Siebert00}, which includes all external management data, freed objects, and reserved memory.
     441\newterm{Internal fragmentation} is memory space that is allocated to the program, but is not intended to be accessed by the program, such as headers, trailers, padding, and spacing around an allocated object.
     442Internal fragmentation is problematic when management space is a significant proportion of an allocated object, \eg for small objects ($<$16 bytes), memory usage is doubled.
     443An allocator should strive to keep internal management information to a minimum.
     444
     445\newterm{External fragmentation} is all memory space reserved from the OS but not allocated to the program~\cite{Wilson95,Lim98,Siebert00}, which includes all external management data, freed objects, and reserved memory.
    431446This memory is problematic in two ways: heap blowup and highly fragmented memory.
    432447\newterm{Heap blowup} occurs when freed memory cannot be reused for future allocations leading to potentially unbounded external fragmentation growth~\cite{Berger00}.
    433 Memory can become \newterm{highly fragmented} after multiple allocations and deallocations of objects, resulting in a checkerboard of adjacent allocated and free areas, where the free blocks are to small to service requests.
     448Memory can become \newterm{highly fragmented} after multiple allocations and deallocations of objects, resulting in a checkerboard of adjacent allocated and free areas, where the free blocks have become to small to service requests.
    434449% Figure~\ref{f:MemoryFragmentation} shows an example of how a small block of memory fragments as objects are allocated and deallocated over time.
    435 Heap blowup occurs with allocator policies that are too restrictive in reusing freed memory, \eg the allocated size cannot use a larger free block and/or no coalescing of free storage.
     450Heap blowup can occur due to allocator policies that are too restrictive in reusing freed memory (the allocated size cannot use a larger free block) and/or no coalescing of free storage.
    436451% Blocks of free memory become smaller and non-contiguous making them less useful in serving allocation requests.
    437452% Memory is highly fragmented when most free blocks are unusable because of their sizes.
     
    464479
    465480The second approach is a \newterm{segregated} or \newterm{binning algorithm} with a set of lists for different sized freed objects.
    466 When an object is allocated, the requested size is rounded up to the nearest bin-size, often leading to space after the object.
     481When an object is allocated, the requested size is rounded up to the nearest bin-size, often leading to spacing after the object.
    467482A binning algorithm is fast at finding free memory of the appropriate size and allocating it, since the first free object on the free list is used.
    468 Fewer bin sizes means a faster search to find a matching bin, but larger differences between allocation and bin size, which increases unusable space after objects (internal fragmentation).
    469 More bin sizes means a slower search but smaller differences matching between allocation and bin size resulting in less internal fragmentation but more external fragmentation if larger bins cannot service smaller requests.
    470 Allowing larger bins to service smaller allocations when the matching bin is empty means the freed object can be returned to the matching or larger bin (some advantages to either scheme).
     483The fewer bin sizes, the fewer lists need to be searched and maintained;
     484however, unusable space after object increases, leading to more internal fragmentation.
     485The more bin sizes, the longer the search and the less likely a matching free objects is found, leading to more external fragmentation and potentially heap blowup.
     486A variation of the binning algorithm allows objects to be allocated from larger bin sizes when the matching bins is empty, and the freed object can be returned to the matching or larger bin (some advantages to either scheme).
    471487% For example, with bin sizes of 8 and 16 bytes, a request for 12 bytes allocates only 12 bytes, but when the object is freed, it is placed on the 8-byte bin-list.
    472488% For subsequent requests, the bin free-lists contain objects of different sizes, ranging from one bin-size to the next (8-16 in this example), and a sequential-fit algorithm may be used to find an object large enough for the requested size on the associated bin list.
    473489
    474 The third approach is a \newterm{splitting} and \newterm{coalescing} algorithms.
    475 When an object is allocated, if there is no matching free storage, a larger free object is split into two smaller objects, one matching the allocation size.
    476 For example, in the \newterm{buddy system}, a block of free memory is split into equal chunks, splitting continues until a minimal block is created that fits the allocation.
    477 When an object is deallocated, it is coalesced with the objects immediately before/after it in memory, if they are free, turning them into a larger block.
     490The third approach is \newterm{splitting} and \newterm{coalescing algorithms}.
     491When an object is allocated, if there are no free objects of the requested size, a larger free object is split into two smaller objects to satisfy the allocation request rather than obtaining more memory from the OS.
     492For example, in the \newterm{buddy system}, a block of free memory is split into equal chunks, one of those chunks is again split, and so on until a minimal block is created that fits the requested object.
     493When an object is deallocated, it is coalesced with the objects immediately before and after it in memory, if they are free, turning them into one larger block.
    478494Coalescing can be done eagerly at each deallocation or lazily when an allocation cannot be fulfilled.
    479 However, coalescing increases allocation latency (unbounded delays), both for allocation and deallocation.
     495In all cases, coalescing increases allocation latency, hence some allocations can cause unbounded delays.
    480496While coalescing does not reduce external fragmentation, the coalesced blocks improve fragmentation quality so future allocations are less likely to cause heap blowup.
    481497% Splitting and coalescing can be used with other algorithms to avoid highly fragmented memory.
     
    488504% Temporal clustering implies a group of objects are accessed repeatedly within a short time period, while spatial clustering implies a group of objects physically close together (nearby addresses) are accessed repeatedly within a short time period.
    489505% Temporal locality commonly occurs during an iterative computation with a fixed set of disjoint variables, while spatial locality commonly occurs when traversing an array.
    490 Hardware takes advantage of the working set through multiple levels of caching and paging, \ie memory hierarchy.
     506Hardware takes advantage of the working set through multiple levels of caching, \ie memory hierarchy.
    491507% When an object is accessed, the memory physically located around the object is also cached with the expectation that the current and nearby objects will be referenced within a short period of time.
    492508For example, entire cache lines are transferred between cache and memory, and entire virtual-memory pages are transferred between memory and disk.
    493509% A program exhibiting good locality has better performance due to fewer cache misses and page faults\footnote{With the advent of large RAM memory, paging is becoming less of an issue in modern programming.}.
    494510
    495 Temporal locality is largely controlled by program accesses to its variables~\cite{Feng05}.
    496 An allocator has only indirect influence on temporal locality but largely dictates spatial locality.
    497 For temporal locality, an allocator tries to return recently freed storage for new allocations, as this memory is still \emph{warm} in the memory hierarchy.
    498 For spatial locality, an allocator places objects used together close together in memory, so the working set of the program fits into the fewest possible cache lines and pages.
     511Temporal locality is largely controlled by how a program accesses its variables~\cite{Feng05}.
     512Nevertheless, a memory allocator can have some indirect influence on temporal locality and largely dictates spatial locality.
     513For temporal locality, an allocator can return storage for new allocations that was just freed as these memory locations are still \emph{warm} in the memory hierarchy.
     514For spatial locality, an allocator can place objects used together close together in memory, so the working set of the program fits into the fewest possible cache lines and pages.
    499515% However, usage patterns are different for every program as is the underlying hardware memory architecture;
    500516% hence, no general-purpose memory-allocator can provide ideal locality for every program on every computer.
    501517
    502 An allocator can easily degrade locality by increasing the working set.
    503 An allocator can access an unbounded number of free objects when matching an allocation or coalescing, causing multiple cache or page misses~\cite{Grunwald93}.
    504 An allocator can spatially separate related data by binning free storage anywhere in memory, so the related objects are highly separated.
     518There are a number of ways a memory allocator can degrade locality by increasing the working set.
     519For example, a memory allocator may access multiple free objects before finding one to satisfy an allocation request, \eg sequential-fit algorithm, which can perturb the program's memory hierarchy causing multiple cache or page misses~\cite{Grunwald93}.
     520Another way locality can be degraded is by spatially separating related data.
     521For example, in a binning allocator, objects of different sizes are allocated from different bins that may be located in different pages of memory.
    505522
    506523
     
    508525\label{s:MultiThreadedMemoryAllocator}
    509526
    510 In a concurrent (multi-threaded) program, multiple program threads performs allocation operations and all concurrency issues arise.
    511 Along with fragmentation and locality issues, a multi-threaded allocator must deal with mutual exclusion, false sharing, and additional forms of heap blowup.
     527A multi-threaded memory-allocator does not run any threads itself, but is used by a multi-threaded program.
     528In addition to single-threaded design issues of fragmentation and locality, a multi-threaded allocator is simultaneously accessed by multiple threads, and hence, must deal with concurrency issues such as mutual exclusion, false sharing, and additional forms of heap blowup.
    512529
    513530
     
    517534\newterm{Mutual exclusion} provides sequential access to the shared-management data of the heap.
    518535There are two performance issues for mutual exclusion.
    519 First is the cost of performing at least one hardware atomic operation every time a shared resource is accessed.
    520 Second is \emph{contention} on simultaneous access, so some threads must wait until the resource is released.
     536First is the overhead necessary to perform (at least) a hardware atomic operation every time a shared resource is accessed.
     537Second is when multiple threads contend for a shared resource simultaneously, and hence, some threads must wait until the resource is released.
    521538Contention can be reduced in a number of ways:
    522 1) Using multiple fine-grained locks versus a single lock to spread the contention across the locks.
    523 2) Using trylock and generating new storage if the lock is busy (classic space versus time tradeoff).
     5391) Using multiple fine-grained locks versus a single lock to spread the contention across a number of locks.
     5402) Using trylock and generating new storage if the lock is busy, yielding a classic space versus time tradeoff.
    5245413) Using one of the many lock-free approaches for reducing contention on basic data-structure operations~\cite{Oyama99}.
    525 However, all approaches have degenerate cases where program contention to the heap is high, which is beyond the allocator's control.
     542However, all of these approaches have degenerate cases where program contention is high, which occurs outside of the allocator.
    526543
    527544
     
    529546\label{s:FalseSharing}
    530547
    531 False sharing occurs when two or more threads simultaneously modify different objects sharing a cache line.
    532 Changes now invalidate each thread's cache, even though the threads may be uninterested in the other modified object.
    533 False sharing can occur three ways:
    534 1) Thread T$_1$ allocates objects O$_1$ and O$_2$ on the same cache line and passes O$_2$'s reference to thread T$_2$;
    535 both threads now simultaneously modifying the objects on the same cache line.
    536 2) Objects O$_1$ and O$_2$ are allocated on the same cache line by thread T$_3$ and their references are passed to T$_1$ and T$_2$, which simultaneously modify the objects.
    537 3) T$_2$ deallocates O$_2$, T$_1$ allocates O$_1$ on the same cache line as O$_2$, and T$_2$ reallocated O$_2$ while T$_1$ is using O$_1$.
    538 In all three cases, the allocator performs a hidden and possibly transient (non-determinism) operation, making it extremely difficult to find and fix the issue.
     548False sharing is a dynamic phenomenon leading to cache thrashing.
     549When two or more threads on separate CPUs simultaneously change different objects sharing a cache line, the change invalidates the other thread's associated cache, even though these threads may be uninterested in the other modified object.
     550False sharing can occur in three different ways: program induced, allocator-induced active, and allocator-induced passive;
     551a memory allocator can only affect the latter two.
     552
     553Specifically, assume two objects, O$_1$ and O$_2$, share a cache line, with threads, T$_1$ and T$_2$.
     554\newterm{Program-induced false-sharing} occurs when T$_1$ passes a reference to O$_2$ to T$_2$, and then T$_1$ modifies O$_1$ while T$_2$ modifies O$_2$.
     555% Figure~\ref{f:ProgramInducedFalseSharing} shows when Thread$_1$ passes Object$_2$ to Thread$_2$, a false-sharing situation forms when Thread$_1$ modifies Object$_1$ and Thread$_2$ modifies Object$_2$.
     556% Changes to Object$_1$ invalidate CPU$_2$'s cache line, and changes to Object$_2$ invalidate CPU$_1$'s cache line.
     557% \begin{figure}
     558% \centering
     559% \subfloat[Program-Induced False-Sharing]{
     560%       \input{ProgramFalseSharing}
     561%       \label{f:ProgramInducedFalseSharing}
     562% } \\
     563% \vspace{5pt}
     564% \subfloat[Allocator-Induced Active False-Sharing]{
     565%       \input{AllocInducedActiveFalseSharing}
     566%       \label{f:AllocatorInducedActiveFalseSharing}
     567% } \\
     568% \vspace{5pt}
     569% \subfloat[Allocator-Induced Passive False-Sharing]{
     570%       \input{AllocInducedPassiveFalseSharing}
     571%       \label{f:AllocatorInducedPassiveFalseSharing}
     572% } subfloat
     573% \caption{False Sharing}
     574% \label{f:FalseSharing}
     575% \end{figure}
     576\newterm{Allocator-induced active false-sharing}\label{s:AllocatorInducedActiveFalseSharing} occurs when O$_1$ and O$_2$ are heap allocated and their references are passed to T$_1$ and T$_2$, which modify the objects.
     577% For example, in Figure~\ref{f:AllocatorInducedActiveFalseSharing}, each thread allocates an object and loads a cache-line of memory into its associated cache.
     578% Again, changes to Object$_1$ invalidate CPU$_2$'s cache line, and changes to Object$_2$ invalidate CPU$_1$'s cache line.
     579\newterm{Allocator-induced passive false-sharing}\label{s:AllocatorInducedPassiveFalseSharing} occurs
     580% is another form of allocator-induced false-sharing caused by program-induced false-sharing.
     581% When an object in a program-induced false-sharing situation is deallocated, a future allocation of that object may cause passive false-sharing.
     582when T$_1$ passes O$_2$ to T$_2$, and T$_2$ subsequently deallocates O$_2$, and then O$_2$ is reallocated to T$_2$ while T$_1$ is still using O$_1$.
    539583
    540584
     
    542586\label{s:HeapBlowup}
    543587
    544 In a multi-threaded program, heap blowup occurs when memory freed by one thread is inaccessible to other threads due to the allocation strategy.
     588In a multi-threaded program, heap blowup can occur when memory freed by one thread is inaccessible to other threads due to the allocation strategy.
    545589Specific examples are presented in later subsections.
    546590
    547591
    548 \subsection{Multi-Threaded Allocator Features}
    549 \label{s:MultiThreadedAllocatorFeatures}
    550 
    551 The following features are used in the construction of multi-threaded allocators.
     592\subsection{Multi-Threaded Memory-Allocator Features}
     593\label{s:MultiThreadedMemoryAllocatorFeatures}
     594
     595The following features are used in the construction of multi-threaded memory-allocators: multiple heaps, user-level threading, ownership, object containers, allocation buffer, lock-free operations.
     596The first feature, multiple heaps, pertains to different kinds of heaps.
     597The second feature, object containers, pertains to the organization of objects within the storage area.
     598The remaining features apply to different parts of the allocator design or implementation.
     599
    552600
    553601\subsubsection{Multiple Heaps}
    554602\label{s:MultipleHeaps}
    555603
    556 Figure~\ref{f:ThreadHeapRelationship} shows how a multi-threaded allocator can subdivide a single global heap into multiple heaps to reduce contention among threads.
     604A multi-threaded allocator has potentially multiple threads and heaps.
     605The multiple threads cause complexity, and multiple heaps are a mechanism for dealing with the complexity.
     606The spectrum ranges from multiple threads using a single heap, denoted as T:1, to multiple threads sharing multiple heaps, denoted as T:H, to one thread per heap, denoted as 1:1, which is almost back to a single-threaded allocator.
    557607
    558608\begin{figure}
     
    576626} % subfloat
    577627\caption{Multiple Heaps, Thread:Heap Relationship}
    578 \label{f:ThreadHeapRelationship}
    579 \end{figure}
    580 
    581 \begin{description}[leftmargin=*]
    582 \item[T:1 model (Figure~\ref{f:SingleHeap})] has all threads allocating and deallocating objects from one heap.
     628\end{figure}
     629
     630\paragraph{T:1 model (see Figure~\ref{f:SingleHeap})} where all threads allocate and deallocate objects from one heap.
    583631Memory is obtained from the freed objects, or reserved memory in the heap, or from the OS;
    584632the heap may also return freed memory to the OS.
    585 The arrows indicate the direction memory moves for each alocation/deallocation operation.
     633The arrows indicate the direction memory conceptually moves for each kind of operation: allocation moves memory along the path from the heap/operating-system to the user application, while deallocation moves memory along the path from the application back to the heap/operating-system.
    586634To safely handle concurrency, a single lock may be used for all heap operations or fine-grained locking for different operations.
    587 Regardless, a single heap is a significant source of contention for threaded programs with a large amount of memory allocations.
    588 
    589 \item[T:H model (Figure~\ref{f:SharedHeaps})] subdivides the heap independently from the threads.
    590 The decision to create a heap and which heap a thread allocates/deallocates during its lifetime depends on the allocator design.
    591 Locking is required within each heap because of multiple tread access, but contention is reduced because fewer threads access a specific heap.
    592 The goal is to have mininal heaps (storage) and thread contention per heap (time).
    593 However, the worst case results in more heaps than threads, \eg if the number of threads is large at startup creating a large number of heaps and then the number of threads reduces.
     635Regardless, a single heap may be a significant source of contention for programs with a large amount of memory allocation.
     636
     637\paragraph{T:H model (see Figure~\ref{f:SharedHeaps})} where each thread allocates storage from several heaps depending on certain criteria, with the goal of reducing contention by spreading allocations/deallocations across the heaps.
     638The decision on when to create a new heap and which heap a thread allocates from depends on the allocator design.
     639To determine which heap to access, each thread must point to its associated heap in some way.
     640The performance goal is to reduce the ratio of heaps to threads.
     641However, the worse case can result in more heaps than threads, \eg if the number of threads is large at startup with many allocations creating a large number of heaps and then the number of threads reduces.
     642Locking is required, since more than one thread may concurrently access a heap during its lifetime, but contention is reduced because fewer threads access a specific heap.
    594643
    595644% For example, multiple heaps are managed in a pool, starting with a single or a fixed number of heaps that increase\-/decrease depending on contention\-/space issues.
     
    644693In general, the cost is minimal since the majority of memory operations are completed without the use of the global heap.
    645694
    646 \item[1:1 model (Figure~\ref{f:PerThreadHeap})] has each thread with its own heap, eliminating most contention and locking because threads seldom access another thread's heap (see Section~\ref{s:Ownership}).
     695\paragraph{1:1 model (see Figure~\ref{f:PerThreadHeap})} where each thread has its own heap eliminating most contention and locking because threads seldom access another thread's heap (see Section~\ref{s:Ownership}).
    647696An additional benefit of thread heaps is improved locality due to better memory layout.
    648697As each thread only allocates from its heap, all objects are consolidated in the storage area for that heap, better utilizing each CPUs cache and accessing fewer pages.
    649698In contrast, the T:H model spreads each thread's objects over a larger area in different heaps.
    650 Thread heaps can also reduces false-sharing, except at crucial boundaries overlapping memory from another thread's heap.
     699Thread heaps can also eliminate allocator-induced active false-sharing, if memory is acquired so it does not overlap at crucial boundaries with memory for another thread's heap.
    651700For example, assume page boundaries coincide with cache line boundaries, if a thread heap always acquires pages of memory then no two threads share a page or cache line unless pointers are passed among them.
    652701% Hence, allocator-induced active false-sharing cannot occur because the memory for thread heaps never overlaps.
     
    657706Destroying the thread heap immediately may reduce external fragmentation sooner, since all free objects are freed to the global heap and may be reused by other threads.
    658707Alternatively, reusing thread heaps may improve performance if the inheriting thread makes similar allocation requests as the thread that previously held the thread heap because any unfreed storage is immediately accessible.
    659 \end{description}
    660708
    661709
  • doc/papers/llheap/figures/AddressSpace.fig

    r03606ce r06601401  
    991200 2
    10102 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    11          1200 1200 2100 1200 2100 1800 1200 1800 1200 1200
    12 2 2 0 1 0 7 60 -1 17 0.000 0 0 -1 0 0 5
    13          2100 1200 3000 1200 3000 1800 2100 1800 2100 1200
     11         5700 1350 6600 1350 6600 2100 5700 2100 5700 1350
     122 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
     13         1200 1350 2100 1350 2100 2100 1200 2100 1200 1350
     142 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
     15         4800 1350 5700 1350 5700 2100 4800 2100 4800 1350
    14162 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    1517        1 1 1.00 45.00 90.00
    16          2100 1500 2400 1500
     18         2100 1725 2400 1725
    17192 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    1820        1 1 1.00 45.00 90.00
    19          3000 1500 2700 1500
    20 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    21          3000 1200 3900 1200 3900 1800 3000 1800 3000 1200
    22 2 2 0 1 0 7 60 -1 17 0.000 0 0 -1 0 0 5
    23          3900 1200 4800 1200 4800 1800 3900 1800 3900 1200
     21         3000 1725 2700 1725
    24222 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    2523        1 1 1.00 45.00 90.00
    26          3900 1500 4200 1500
     24         3900 1725 4200 1725
    27252 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
    2826        1 1 1.00 45.00 90.00
    29          4800 1500 4500 1500
     27         4800 1725 4500 1725
     282 2 0 1 0 7 60 -1 17 0.000 0 0 -1 0 0 5
     29         2100 1350 3000 1350 3000 2100 2100 2100 2100 1350
    30302 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    31          4800 1200 5700 1200 5700 1800 4800 1800 4800 1200
    32 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
    33          5700 1200 6600 1200 6600 1800 5700 1800 5700 1200
    34 4 0 0 50 -1 0 10 0.0000 2 165 870 1200 2025 high address\001
    35 4 2 0 50 -1 0 10 0.0000 2 120 810 6600 2025 low address\001
    36 4 1 0 50 -1 0 10 0.0000 2 120 375 1650 1575 Stack\001
    37 4 1 0 50 -1 0 10 0.0000 2 150 600 2550 1725 Memory\001
    38 4 1 0 50 -1 0 10 0.0000 2 120 300 2550 1425 Free\001
    39 4 1 0 50 -1 0 10 0.0000 2 120 660 3450 1575 Code and\001
    40 4 1 0 50 -1 0 10 0.0000 2 150 630 3450 1350 Dynamic\001
    41 4 1 0 50 -1 0 10 0.0000 2 120 315 3450 1775 Data\001
    42 4 1 0 50 -1 0 10 0.0000 2 120 300 4350 1425 Free\001
    43 4 1 0 50 -1 0 10 0.0000 2 150 600 4350 1725 Memory\001
    44 4 1 4 50 -1 0 10 0.0000 2 150 630 5250 1425 Dynamic\001
    45 4 1 0 50 -1 0 10 0.0000 2 120 315 6150 1775 Data\001
    46 4 1 0 50 -1 0 10 0.0000 2 120 660 6150 1575 Code and\001
    47 4 1 0 50 -1 0 10 0.0000 2 120 375 6150 1350 Static\001
    48 4 1 4 50 -1 0 10 0.0000 2 120 720 5250 1725 Allocation\001
     31         3000 1350 3900 1350 3900 2100 3000 2100 3000 1350
     322 2 0 1 0 7 60 -1 17 0.000 0 0 -1 0 0 5
     33         3900 1350 4800 1350 4800 2100 3900 2100 3900 1350
     344 0 0 50 -1 0 10 0.0000 2 180 900 1200 2325 high address\001
     354 2 0 50 -1 0 10 0.0000 2 135 855 6600 2325 low address\001
     364 1 0 50 -1 0 10 0.0000 2 120 330 6150 2025 Data\001
     374 1 0 50 -1 0 10 0.0000 2 135 675 6150 1800 Code and\001
     384 1 0 50 -1 0 10 0.0000 2 120 390 6150 1575 Static\001
     394 1 0 50 -1 0 10 0.0000 2 135 390 1650 1800 Stack\001
     404 1 0 50 -1 0 10 0.0000 2 165 615 2550 1950 Memory\001
     414 1 0 50 -1 0 10 0.0000 2 165 615 4350 1950 Memory\001
     424 1 0 50 -1 0 10 0.0000 2 120 315 2550 1650 Free\001
     434 1 0 50 -1 0 10 0.0000 2 120 330 3450 2025 Data\001
     444 1 0 50 -1 0 10 0.0000 2 135 675 3450 1800 Code and\001
     454 1 0 50 -1 0 10 0.0000 2 165 645 3450 1575 Dynamic\001
     464 1 0 50 -1 0 10 0.0000 2 120 315 4350 1650 Free\001
     474 1 0 50 -1 0 10 0.0000 2 120 735 5250 1950 Allocation\001
     484 1 0 50 -1 0 10 0.0000 2 165 645 5250 1650 Dynamic\001
  • doc/theses/mike_brooks_MMath/programs/sharing-demo.cfa

    r03606ce r06601401  
    144144        sout | xstr(D2_s1_abcd) | "\t\\\\";
    145145
    146         #define D2_s1mid_s1 string s1_mid = s1(1,2)`shareEdits
     146        #define D2_s1mid_s1 string s1_mid = s1(1,3)`shareEdits
    147147        D2_s1mid_s1;
    148148        sout | xstr(D2_s1mid_s1) | "\t\\\\";
    149149
    150         #define D2_s2_s1 string s2     = s1(1,2)
     150        #define D2_s2_s1 string s2     = s1(1,3)
    151151        D2_s2_s1;     
    152152        assert( s1 == "abcd" );
     
    257257        sout  | xstr(D2_s1bgn_s1)  | "\t\\\\";
    258258
    259         #define D2_s1end_s1 string s1_end = s1(3, 1)`shareEdits
     259        #define D2_s1end_s1 string s1_end = s1(3, 4)`shareEdits
    260260        D2_s1end_s1;
    261261        assert( s1 == "ajjd" );
     
    280280        sout | "\t\t\t\t& @s1@\t& @s1_bgn@\t& @s1_crs@\t& @s1_mid@\t& @s1_end@\t\\\\";
    281281   
    282         #define D2_s1crs_s1 string s1_crs = s1(3, 2)`shareEdits
     282        #define D2_s1crs_s1 string s1_crs = s1(3, 5)`shareEdits
    283283        D2_s1crs_s1;
    284284        assert( s1 == "zzzzjjd" );
     
    305305        string word = "Phi";
    306306        string consonants = word(0,2)`shareEdits;
    307         string miniscules = word(1,2)`shareEdits;
     307        string miniscules = word(1,3)`shareEdits;
    308308        assert( word == "Phi" );
    309309        assert( consonants == "Ph" );
     
    318318   
    319319        string all = "They said hello again";
    320         string greet     = all(10,5)`shareEdits;
    321         string greet_bgn = all(10,1)`shareEdits;
    322         string greet_end = all(14,1)`shareEdits;
     320        string greet     = all(10,15)`shareEdits;
     321        string greet_bgn = all(10,11)`shareEdits;
     322        string greet_end = all(14,15)`shareEdits;
    323323     
    324324        assert( all == "They said hello again" );
  • src/Parser/DeclarationNode.cc

    r03606ce r06601401  
    177177}
    178178
    179 DeclarationNode * DeclarationNode::newFromTypeData( TypeData * type ) {
    180         DeclarationNode * newnode = new DeclarationNode;
    181         newnode->type = type;
    182         return newnode;
    183 } // DeclarationNode::newFromTypeData
    184 
    185179DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) {
    186180        DeclarationNode * newnode = new DeclarationNode;
     
    194188        return newnode;
    195189} // DeclarationNode::newFuncSpecifier
     190
     191DeclarationNode * DeclarationNode::newTypeQualifier( ast::CV::Qualifiers tq ) {
     192        DeclarationNode * newnode = new DeclarationNode;
     193        newnode->type = new TypeData();
     194        newnode->type->qualifiers = tq;
     195        return newnode;
     196} // DeclarationNode::newQualifier
     197
     198DeclarationNode * DeclarationNode::newBasicType( BasicType bt ) {
     199        DeclarationNode * newnode = new DeclarationNode;
     200        newnode->type = new TypeData( TypeData::Basic );
     201        newnode->type->basictype = bt;
     202        return newnode;
     203} // DeclarationNode::newBasicType
     204
     205DeclarationNode * DeclarationNode::newComplexType( ComplexType ct ) {
     206        DeclarationNode * newnode = new DeclarationNode;
     207        newnode->type = new TypeData( TypeData::Basic );
     208        newnode->type->complextype = ct;
     209        return newnode;
     210} // DeclarationNode::newComplexType
     211
     212DeclarationNode * DeclarationNode::newSignedNess( Signedness sn ) {
     213        DeclarationNode * newnode = new DeclarationNode;
     214        newnode->type = new TypeData( TypeData::Basic );
     215        newnode->type->signedness = sn;
     216        return newnode;
     217} // DeclarationNode::newSignedNess
     218
     219DeclarationNode * DeclarationNode::newLength( Length lnth ) {
     220        DeclarationNode * newnode = new DeclarationNode;
     221        newnode->type = new TypeData( TypeData::Basic );
     222        newnode->type->length = lnth;
     223        return newnode;
     224} // DeclarationNode::newLength
     225
     226DeclarationNode * DeclarationNode::newForall( DeclarationNode * forall ) {
     227        DeclarationNode * newnode = new DeclarationNode;
     228        newnode->type = new TypeData( TypeData::Unknown );
     229        newnode->type->forall = forall;
     230        return newnode;
     231} // DeclarationNode::newForall
     232
     233DeclarationNode * DeclarationNode::newFromGlobalScope() {
     234        DeclarationNode * newnode = new DeclarationNode;
     235        newnode->type = new TypeData( TypeData::GlobalScope );
     236        return newnode;
     237}
     238
     239DeclarationNode * DeclarationNode::newQualifiedType( DeclarationNode * parent, DeclarationNode * child) {
     240        DeclarationNode * newnode = new DeclarationNode;
     241        newnode->type = new TypeData( TypeData::Qualified );
     242        newnode->type->qualified.parent = parent->type;
     243        newnode->type->qualified.child = child->type;
     244        parent->type = nullptr;
     245        child->type = nullptr;
     246        delete parent;
     247        delete child;
     248        return newnode;
     249}
    196250
    197251DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
     
    258312}
    259313
     314DeclarationNode * DeclarationNode::newFromTypedef( const string * name ) {
     315        DeclarationNode * newnode = new DeclarationNode;
     316        newnode->type = new TypeData( TypeData::SymbolicInst );
     317        newnode->type->symbolic.name = name;
     318        newnode->type->symbolic.isTypedef = true;
     319        newnode->type->symbolic.params = nullptr;
     320        return newnode;
     321} // DeclarationNode::newFromTypedef
     322
     323DeclarationNode * DeclarationNode::newFromTypeGen( const string * name, ExpressionNode * params ) {
     324        DeclarationNode * newnode = new DeclarationNode;
     325        newnode->type = new TypeData( TypeData::SymbolicInst );
     326        newnode->type->symbolic.name = name;
     327        newnode->type->symbolic.isTypedef = false;
     328        newnode->type->symbolic.actuals = params;
     329        return newnode;
     330} // DeclarationNode::newFromTypeGen
     331
    260332DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) {
    261333        DeclarationNode * newnode = newName( name );
     
    351423        return newnode;
    352424}
     425
     426DeclarationNode * DeclarationNode::newVtableType( DeclarationNode * decl ) {
     427        DeclarationNode * newnode = new DeclarationNode;
     428        newnode->type = new TypeData( TypeData::Vtable );
     429        newnode->setBase( decl->type );
     430        return newnode;
     431}
     432
     433DeclarationNode * DeclarationNode::newBuiltinType( BuiltinType bt ) {
     434        DeclarationNode * newnode = new DeclarationNode;
     435        newnode->type = new TypeData( TypeData::Builtin );
     436        newnode->type->builtintype = bt;
     437        return newnode;
     438} // DeclarationNode::newBuiltinType
    353439
    354440DeclarationNode * DeclarationNode::newFunction( const string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body ) {
  • src/Parser/DeclarationNode.h

    r03606ce r06601401  
    4040        static const char * builtinTypeNames[];
    4141
    42         static DeclarationNode * newFromTypeData( TypeData * );
    4342        static DeclarationNode * newStorageClass( ast::Storage::Classes );
    4443        static DeclarationNode * newFuncSpecifier( ast::Function::Specs );
     44        static DeclarationNode * newTypeQualifier( ast::CV::Qualifiers );
     45        static DeclarationNode * newBasicType( BasicType );
     46        static DeclarationNode * newComplexType( ComplexType );
     47        static DeclarationNode * newSignedNess( Signedness );
     48        static DeclarationNode * newLength( Length );
     49        static DeclarationNode * newBuiltinType( BuiltinType );
     50        static DeclarationNode * newForall( DeclarationNode * );
     51        static DeclarationNode * newFromTypedef( const std::string * );
     52        static DeclarationNode * newFromGlobalScope();
     53        static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );
    4554        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    4655        static DeclarationNode * newAggregate( ast::AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
     
    5059        static DeclarationNode * newEnumInLine( const std::string name );
    5160        static DeclarationNode * newName( const std::string * );
     61        static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );
    5262        static DeclarationNode * newTypeParam( ast::TypeDecl::Kind, const std::string * );
    5363        static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );
     
    6070        static DeclarationNode * newTuple( DeclarationNode * members );
    6171        static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );
     72        static DeclarationNode * newVtableType( DeclarationNode * expr );
    6273        static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    6374        static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement
     
    152163}; // DeclarationNode
    153164
     165ast::Type * buildType( TypeData * type );
     166
    154167static inline ast::Type * maybeMoveBuildType( const DeclarationNode * orig ) {
    155168        ast::Type * ret = orig ? orig->buildType() : nullptr;
  • src/Parser/ExpressionNode.cc

    r03606ce r06601401  
    2929#include "DeclarationNode.h"       // for DeclarationNode
    3030#include "InitializerNode.h"       // for InitializerNode
    31 #include "TypeData.h"              // for addType, build_basic_type, build_c...
    3231#include "parserutility.h"         // for notZeroExpr
    3332
     
    317316                                v2 );
    318317                        ret = build_compoundLiteral( location,
    319                                 DeclarationNode::newFromTypeData(
    320                                         addType(
    321                                                 build_basic_type( DeclarationNode::Int128 ),
    322                                                 build_signedness( DeclarationNode::Unsigned ) ) ),
     318                                DeclarationNode::newBasicType(
     319                                        DeclarationNode::Int128
     320                                )->addType(
     321                                        DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
    323322                                new InitializerNode(
    324                                         (new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true )
     323                                        (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true )
    325324                        );
    326325                } else {                                                                                // explicit length, (length_type)constant
  • src/Parser/TypeData.cc

    r03606ce r06601401  
    478478}
    479479
     480
    480481TypeData * TypeData::getLastBase() {
    481482        TypeData * cur = this;
     
    486487void TypeData::setLastBase( TypeData * newBase ) {
    487488        getLastBase()->base = newBase;
    488 }
    489 
    490 
    491 TypeData * build_type_qualifier( ast::CV::Qualifiers tq ) {
    492         TypeData * type = new TypeData;
    493         type->qualifiers = tq;
    494         return type;
    495 }
    496 
    497 TypeData * build_basic_type( DeclarationNode::BasicType basic ) {
    498         TypeData * type = new TypeData( TypeData::Basic );
    499         type->basictype = basic;
    500         return type;
    501 }
    502 
    503 TypeData * build_complex_type( DeclarationNode::ComplexType complex ) {
    504         TypeData * type = new TypeData( TypeData::Basic );
    505         type->complextype = complex;
    506         return type;
    507 }
    508 
    509 TypeData * build_signedness( DeclarationNode::Signedness signedness ) {
    510         TypeData * type = new TypeData( TypeData::Basic );
    511         type->signedness = signedness;
    512         return type;
    513 }
    514 
    515 TypeData * build_builtin_type( DeclarationNode::BuiltinType bit ) {
    516         TypeData * type = new TypeData( TypeData::Builtin );
    517         type->builtintype = bit;
    518         return type;
    519 }
    520 
    521 TypeData * build_length( DeclarationNode::Length length ) {
    522         TypeData * type = new TypeData( TypeData::Basic );
    523         type->length = length;
    524         return type;
    525 }
    526 
    527 TypeData * build_forall( DeclarationNode * forall ) {
    528         TypeData * type = new TypeData( TypeData::Unknown );
    529         type->forall = forall;
    530         return type;
    531 }
    532 
    533 TypeData * build_global_scope() {
    534         return new TypeData( TypeData::GlobalScope );
    535 }
    536 
    537 TypeData * build_qualified_type( TypeData * parent, TypeData * child ) {
    538         TypeData * type = new TypeData( TypeData::Qualified );
    539         type->qualified.parent = parent;
    540         type->qualified.child = child;
    541         return type;
    542 }
    543 
    544 TypeData * build_typedef( const std::string * name ) {
    545         TypeData * type = new TypeData( TypeData::SymbolicInst );
    546         type->symbolic.name = name;
    547         type->symbolic.isTypedef = true;
    548         type->symbolic.actuals = nullptr;
    549         return type;
    550 }
    551 
    552 TypeData * build_type_gen( const std::string * name, ExpressionNode * params ) {
    553         TypeData * type = new TypeData( TypeData::SymbolicInst );
    554         type->symbolic.name = name;
    555         type->symbolic.isTypedef = false;
    556         type->symbolic.actuals = params;
    557         return type;
    558 }
    559 
    560 TypeData * build_vtable_type( TypeData * base ) {
    561         TypeData * type = new TypeData( TypeData::Vtable );
    562         type->base = base;
    563         return type;
    564489}
    565490
     
    702627                return rtype;
    703628        } // if
    704 }
    705 
    706 TypeData * addType( TypeData * ltype, TypeData * rtype ) {
    707         std::vector<ast::ptr<ast::Attribute>> attributes;
    708         return addType( ltype, rtype, attributes );
    709629}
    710630
  • src/Parser/TypeData.h

    r03606ce r06601401  
    116116};
    117117
    118 
    119 TypeData * build_type_qualifier( ast::CV::Qualifiers );
    120 TypeData * build_basic_type( DeclarationNode::BasicType );
    121 TypeData * build_complex_type( DeclarationNode::ComplexType );
    122 TypeData * build_signedness( DeclarationNode::Signedness );
    123 TypeData * build_builtin_type( DeclarationNode::BuiltinType );
    124 TypeData * build_length( DeclarationNode::Length );
    125 TypeData * build_forall( DeclarationNode * );
    126 TypeData * build_global_scope();
    127 TypeData * build_qualified_type( TypeData *, TypeData * );
    128 TypeData * build_typedef( const std::string * name );
    129 TypeData * build_type_gen( const std::string * name, ExpressionNode * params );
    130 TypeData * build_vtable_type( TypeData * );
    131 
    132118TypeData * addQualifiers( TypeData * ltype, TypeData * rtype );
    133119TypeData * addType( TypeData * ltype, TypeData * rtype, std::vector<ast::ptr<ast::Attribute>> & );
    134 TypeData * addType( TypeData * ltype, TypeData * rtype );
    135120TypeData * cloneBaseType( TypeData * type, TypeData * other );
    136121TypeData * makeNewBase( TypeData * type );
    137 
    138122
    139123ast::Type * typebuild( const TypeData * );
     
    160144void buildKRFunction( const TypeData::Function_t & function );
    161145
    162 static inline ast::Type * maybeMoveBuildType( TypeData * type ) {
    163         ast::Type * ret = type ? typebuild( type ) : nullptr;
    164         delete type;
    165         return ret;
    166 }
    167 
    168146// Local Variables: //
    169147// tab-width: 4 //
  • src/Parser/TypedefTable.cc

    r03606ce r06601401  
    2020#include <string>                                                                               // for string
    2121#include <iostream>                                                                             // for iostream
    22 
    23 struct TypeData;
    2422
    2523#include "ExpressionNode.h"                                                             // for LabelNode
  • src/Parser/parser.yy

    r03606ce r06601401  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  6 10:51:55 2024
    13 // Update Count     : 6588
     12// Last Modified On : Mon Mar  4 08:44:25 2024
     13// Update Count     : 6562
    1414//
    1515
     
    317317
    318318%union {
    319         // A raw token can be used.
    320319        Token tok;
    321 
    322         // The general node types hold some generic node or list of nodes.
     320        ExpressionNode * expr;
    323321        DeclarationNode * decl;
    324         InitializerNode * init;
    325         ExpressionNode * expr;
     322        ast::AggregateDecl::Aggregate aggKey;
     323        ast::TypeDecl::Kind tclass;
    326324        StatementNode * stmt;
    327325        ClauseNode * clause;
    328         TypeData * type;
    329 
    330         // Special "nodes" containing compound information.
     326        ast::WaitForStmt * wfs;
     327    ast::WaitUntilStmt::ClauseNode * wucn;
    331328        CondCtl * ifctl;
    332329        ForCtrl * forctl;
    333330        LabelNode * labels;
    334 
    335         // Various flags and single values that become fields later.
    336         ast::AggregateDecl::Aggregate aggKey;
    337         ast::TypeDecl::Kind tclass;
     331        InitializerNode * init;
    338332        OperKinds oper;
     333        std::string * str;
    339334        bool is_volatile;
    340335        EnumHiding enum_hiding;
    341336        ast::ExceptionKind except_kind;
    342         // String passes ownership with it.
    343         std::string * str;
    344 
    345         // Narrower node types are used to avoid constant unwrapping.
    346         ast::WaitForStmt * wfs;
    347         ast::WaitUntilStmt::ClauseNode * wucn;
    348337        ast::GenericExpr * genexpr;
    349338}
     
    475464
    476465%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type
    477 %type<type> basic_type_name_type
    478 %type<type> vtable vtable_opt default_opt
     466%type<decl> vtable vtable_opt default_opt
    479467
    480468%type<decl> trait_declaration trait_declaration_list trait_declaring_list trait_specifier
     
    531519%type<decl> type_declarator type_declarator_name type_declaring_list
    532520
    533 %type<decl> type_declaration_specifier type_type_specifier
    534 %type<type> type_name typegen_name
     521%type<decl> type_declaration_specifier type_type_specifier type_name typegen_name
    535522%type<decl> typedef_name typedef_declaration typedef_expression
    536523
     
    545532%type<expr> type_parameters_opt type_list array_type_list // array_dimension_list
    546533
    547 %type<decl> type_qualifier forall type_qualifier_list_opt type_qualifier_list
    548 %type<type> type_qualifier_name
     534%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
    549535%type<decl> type_specifier type_specifier_nobody
    550536
     
    701687                { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
    702688        | TYPEDIMname                                                                           // CFA, generic length argument
     689                // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); }
     690                // { $$ = new ExpressionNode( build_varref( $1 ) ); }
    703691                { $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); }
    704692        | tuple
     
    708696                { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); }
    709697        | type_name '.' identifier                                                      // CFA, nested type
    710                 { $$ = new ExpressionNode( build_qualified_expr( yylloc, DeclarationNode::newFromTypeData( $1 ), build_varref( yylloc, $3 ) ) ); }
     698                { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    711699        | type_name '.' '[' field_name_list ']'                         // CFA, nested type / tuple field selector
    712700                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     
    763751                // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
    764752                // Current: Commas in subscripts make tuples.
    765                 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, $3->set_last( $5 ) ) ) ) ); }
     753                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
    766754        | postfix_expression '[' assignment_expression ']'
    767755                // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a
     
    778766                        Token fn;
    779767                        fn.str = new std::string( "?{}" );                      // location undefined - use location of '{'?
    780                         $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), $1->set_last( $3 ) ) ) );
     768                        $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    781769                }
    782770        | postfix_expression '(' argument_expression_list_opt ')'
     
    784772        | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')'
    785773                // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; }
    786                 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg" ) ) ),
    787                                                                                            $3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) ) ) ); }
     774                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ),
     775                                                                                           (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); }
    788776        | postfix_expression '`' identifier                                     // CFA, postfix call
    789777                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
     
    843831                        Token fn;
    844832                        fn.str = new string( "^?{}" );                          // location undefined
    845                         $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), $2->set_last( $4 ) ) );
     833                        $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
    846834                }
    847835        ;
     
    856844        argument_expression
    857845        | argument_expression_list_opt ',' argument_expression
    858                 { $$ = $1->set_last( $3 ); }
     846                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
    859847        ;
    860848
     
    868856field_name_list:                                                                                // CFA, tuple field selector
    869857        field
    870         | field_name_list ',' field                                     { $$ = $1->set_last( $3 ); }
     858        | field_name_list ',' field                                     { $$ = (ExpressionNode *)($1->set_last( $3 )); }
    871859        ;
    872860
     
    950938        | ALIGNOF '(' type_no_function ')'                                      // GCC, type alignment
    951939                { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    952 
    953                 // Cannot use rule "type", which includes cfa_abstract_function, for sizeof/alignof, because of S/R problems on
    954                 // look ahead, so the cfa_abstract_function is factored out.
    955         | SIZEOF '(' cfa_abstract_function ')'
    956                 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    957         | ALIGNOF '(' cfa_abstract_function ')'                         // GCC, type alignment
    958                 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    959 
    960940        | OFFSETOF '(' type_no_function ',' identifier ')'
    961941                { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); }
    962         | TYPEID '(' type ')'
     942        | TYPEID '(' type_no_function ')'
    963943                {
    964944                        SemanticError( yylloc, "typeid name is currently unimplemented." ); $$ = nullptr;
     
    990970                { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
    991971        | '(' VIRTUAL ')' cast_expression                                       // CFA
    992                 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), nullptr ) ); }
     972                { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }
    993973        | '(' VIRTUAL type_no_function ')' cast_expression      // CFA
    994974                { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
     
    11621142//              { $$ = new ExpressionNode( build_tuple( $3 ) ); }
    11631143        '[' ',' tuple_expression_list ']'
    1164                 { $$ = new ExpressionNode( build_tuple( yylloc, (new ExpressionNode( nullptr ))->set_last( $3 ) ) ); }
     1144                { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
    11651145        | '[' push assignment_expression pop ',' tuple_expression_list ']'
    1166                 { $$ = new ExpressionNode( build_tuple( yylloc, $3->set_last( $6 ) ) ); }
     1146                { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); }
    11671147        ;
    11681148
     
    11721152                { SemanticError( yylloc, "Eliding tuple element with '@' is currently unimplemented." ); $$ = nullptr; }
    11731153        | tuple_expression_list ',' assignment_expression
    1174                 { $$ = $1->set_last( $3 ); }
     1154                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
    11751155        | tuple_expression_list ',' '@'
    11761156                { SemanticError( yylloc, "Eliding tuple element with '@' is currently unimplemented." ); $$ = nullptr; }
     
    12581238                { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
    12591239        | statement_list_nodecl error                                           // invalid syntax rule
    1260                 { SemanticError( yylloc, "syntax error, declarations only allowed at the start of the switch body,"
    1261                                                  " i.e., after the '{'." ); $$ = nullptr; }
     1240                { SemanticError( yylloc, "syntax error, declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; }
    12621241        ;
    12631242
     
    12671246        ;
    12681247
    1269 // "if", "switch", and "choose" require parenthesis around the conditional. See the following ambiguities without
    1270 // parenthesis:
    1271 //
    1272 //   if x + y + z; => "if ( x + y ) + z" or "if ( x ) + y + z"
    1273 //
    1274 //   switch O { }
    1275 //
    1276 //     O{} => object-constructor for conditional, switch body ???
    1277 //     O{} => O for conditional followed by switch body
    1278 //
    1279 //     C++ has this problem, as it has the same constructor syntax.
    1280 //
    1281 //   switch sizeof ( T ) { }
    1282 //
    1283 //     sizeof ( T ) => sizeof of T for conditional followed by switch body
    1284 //     sizeof ( T ) => sizeof of compound literal (T){ }, closing parenthesis ???
    1285 //
    1286 //     Note the two grammar rules for sizeof (alignof)
    1287 //
    1288 //       | SIZEOF unary_expression
    1289 //       | SIZEOF '(' type_no_function ')'
    1290 //
    1291 //     where the first DOES NOT require parenthesis! And C++ inherits this problem from C.
     1248// if, switch, and choose require parenthesis around the conditional because it can be followed by a statement.
     1249// For example, without parenthesis:
     1250//
     1251//    if x + y + z; => "if ( x + y ) + z" or "if ( x ) + y + z"
     1252//    switch ( S ) { ... } => switch ( S ) { compound literal... } ... or
    12921253
    12931254selection_statement:
     
    13071268                        // therefore, are removed from the grammar even though C allows it. The change also applies to choose
    13081269                        // statement.
    1309                         $$ = $7 ? new StatementNode( build_compound( yylloc, (new StatementNode( $7 ))->set_last( sw ) ) ) : sw;
     1270                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    13101271                }
    13111272        | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, invalid syntax rule error
     
    13161277                {
    13171278                        StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) );
    1318                         $$ = $7 ? new StatementNode( build_compound( yylloc, (new StatementNode( $7 ))->set_last( sw ) ) ) : sw;
     1279                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    13191280                }
    13201281        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, invalid syntax rule
     
    17181679        cast_expression
    17191680        | cast_expression_list ',' cast_expression
     1681                // { $$ = (ExpressionNode *)($1->set_last( $3 )); }
    17201682                { SemanticError( yylloc, "List of mutex member is currently unimplemented." ); $$ = nullptr; }
    17211683        ;
     
    17331695                { $$ = $3; }
    17341696        | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
    1735                 { $$ = $3->set_last( $5 ); }
     1697                { $$ = (ExpressionNode *)($3->set_last( $5 )); }
    17361698        ;
    17371699
     
    18891851        asm_operand
    18901852        | asm_operands_list ',' asm_operand
    1891                 { $$ = $1->set_last( $3 ); }
     1853                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
    18921854        ;
    18931855
     
    19081870                { $$ = $1; }
    19091871        | asm_clobbers_list_opt ',' string_literal
    1910                 { $$ = $1->set_last( $3 ); }
     1872                { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); }
    19111873        ;
    19121874
     
    22262188type_qualifier:
    22272189        type_qualifier_name
    2228                 { $$ = DeclarationNode::newFromTypeData( $1 ); }
    22292190        | attribute                                                                                     // trick handles most attribute locations
    22302191        ;
     
    22322193type_qualifier_name:
    22332194        CONST
    2234                 { $$ = build_type_qualifier( ast::CV::Const ); }
     2195                { $$ = DeclarationNode::newTypeQualifier( ast::CV::Const ); }
    22352196        | RESTRICT
    2236                 { $$ = build_type_qualifier( ast::CV::Restrict ); }
     2197                { $$ = DeclarationNode::newTypeQualifier( ast::CV::Restrict ); }
    22372198        | VOLATILE
    2238                 { $$ = build_type_qualifier( ast::CV::Volatile ); }
     2199                { $$ = DeclarationNode::newTypeQualifier( ast::CV::Volatile ); }
    22392200        | ATOMIC
    2240                 { $$ = build_type_qualifier( ast::CV::Atomic ); }
    2241 
    2242                 // forall must be a CV qualifier because it can appear in places where SC qualifiers are disallowed.
    2243                 //
    2244                 //   void foo( forall( T ) T (*)( T ) ); // forward declaration
    2245                 //   void bar( static int ); // static disallowed (gcc/CFA)
     2201                { $$ = DeclarationNode::newTypeQualifier( ast::CV::Atomic ); }
    22462202        | forall
    2247                 { $$ = build_forall( $1 ); }
     2203                { $$ = DeclarationNode::newForall( $1 ); }
    22482204        ;
    22492205
     
    22952251
    22962252basic_type_name:
    2297         basic_type_name_type
    2298                 { $$ = DeclarationNode::newFromTypeData( $1 ); }
    2299         ;
    2300 
    2301 // Just an intermediate value for conversion.
    2302 basic_type_name_type:
    23032253        VOID
    2304                 { $$ = build_basic_type( DeclarationNode::Void ); }
     2254                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
    23052255        | BOOL                                                                                          // C99
    2306                 { $$ = build_basic_type( DeclarationNode::Bool ); }
     2256                { $$ = DeclarationNode::newBasicType( DeclarationNode::Bool ); }
    23072257        | CHAR
    2308                 { $$ = build_basic_type( DeclarationNode::Char ); }
     2258                { $$ = DeclarationNode::newBasicType( DeclarationNode::Char ); }
    23092259        | INT
    2310                 { $$ = build_basic_type( DeclarationNode::Int ); }
     2260                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int ); }
    23112261        | INT128
    2312                 { $$ = build_basic_type( DeclarationNode::Int128 ); }
     2262                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 ); }
    23132263        | UINT128
    2314                 { $$ = addType( build_basic_type( DeclarationNode::Int128 ), build_signedness( DeclarationNode::Unsigned ) ); }
     2264                { $$ = DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ); }
    23152265        | FLOAT
    2316                 { $$ = build_basic_type( DeclarationNode::Float ); }
     2266                { $$ = DeclarationNode::newBasicType( DeclarationNode::Float ); }
    23172267        | DOUBLE
    2318                 { $$ = build_basic_type( DeclarationNode::Double ); }
     2268                { $$ = DeclarationNode::newBasicType( DeclarationNode::Double ); }
    23192269        | uuFLOAT80
    2320                 { $$ = build_basic_type( DeclarationNode::uuFloat80 ); }
     2270                { $$ = DeclarationNode::newBasicType( DeclarationNode::uuFloat80 ); }
    23212271        | uuFLOAT128
    2322                 { $$ = build_basic_type( DeclarationNode::uuFloat128 ); }
     2272                { $$ = DeclarationNode::newBasicType( DeclarationNode::uuFloat128 ); }
    23232273        | uFLOAT16
    2324                 { $$ = build_basic_type( DeclarationNode::uFloat16 ); }
     2274                { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat16 ); }
    23252275        | uFLOAT32
    2326                 { $$ = build_basic_type( DeclarationNode::uFloat32 ); }
     2276                { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat32 ); }
    23272277        | uFLOAT32X
    2328                 { $$ = build_basic_type( DeclarationNode::uFloat32x ); }
     2278                { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat32x ); }
    23292279        | uFLOAT64
    2330                 { $$ = build_basic_type( DeclarationNode::uFloat64 ); }
     2280                { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat64 ); }
    23312281        | uFLOAT64X
    2332                 { $$ = build_basic_type( DeclarationNode::uFloat64x ); }
     2282                { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat64x ); }
    23332283        | uFLOAT128
    2334                 { $$ = build_basic_type( DeclarationNode::uFloat128 ); }
     2284                { $$ = DeclarationNode::newBasicType( DeclarationNode::uFloat128 ); }
    23352285        | DECIMAL32
    23362286                { SemanticError( yylloc, "_Decimal32 is currently unimplemented." ); $$ = nullptr; }
     
    23402290                { SemanticError( yylloc, "_Decimal128 is currently unimplemented." ); $$ = nullptr; }
    23412291        | COMPLEX                                                                                       // C99
    2342                 { $$ = build_complex_type( DeclarationNode::Complex ); }
     2292                { $$ = DeclarationNode::newComplexType( DeclarationNode::Complex ); }
    23432293        | IMAGINARY                                                                                     // C99
    2344                 { $$ = build_complex_type( DeclarationNode::Imaginary ); }
     2294                { $$ = DeclarationNode::newComplexType( DeclarationNode::Imaginary ); }
    23452295        | SIGNED
    2346                 { $$ = build_signedness( DeclarationNode::Signed ); }
     2296                { $$ = DeclarationNode::newSignedNess( DeclarationNode::Signed ); }
    23472297        | UNSIGNED
    2348                 { $$ = build_signedness( DeclarationNode::Unsigned ); }
     2298                { $$ = DeclarationNode::newSignedNess( DeclarationNode::Unsigned ); }
    23492299        | SHORT
    2350                 { $$ = build_length( DeclarationNode::Short ); }
     2300                { $$ = DeclarationNode::newLength( DeclarationNode::Short ); }
    23512301        | LONG
    2352                 { $$ = build_length( DeclarationNode::Long ); }
     2302                { $$ = DeclarationNode::newLength( DeclarationNode::Long ); }
    23532303        | VA_LIST                                                                                       // GCC, __builtin_va_list
    2354                 { $$ = build_builtin_type( DeclarationNode::Valist ); }
     2304                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Valist ); }
    23552305        | AUTO_TYPE
    2356                 { $$ = build_builtin_type( DeclarationNode::AutoType ); }
     2306                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::AutoType ); }
    23572307        | vtable
    23582308        ;
     
    23662316vtable:
    23672317        VTABLE '(' type_name ')' default_opt
    2368                 { $$ = build_vtable_type( $3 ); }
     2318                { $$ = DeclarationNode::newVtableType( $3 ); }
     2319                // { SemanticError( yylloc, "vtable is currently unimplemented." ); $$ = nullptr; }
    23692320        ;
    23702321
     
    24162367                { $$ = DeclarationNode::newTypeof( $3, true ); }
    24172368        | ZERO_T                                                                                        // CFA
    2418                 { $$ = DeclarationNode::newFromTypeData( build_builtin_type( DeclarationNode::Zero ) ); }
     2369                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Zero ); }
    24192370        | ONE_T                                                                                         // CFA
    2420                 { $$ = DeclarationNode::newFromTypeData( build_builtin_type( DeclarationNode::One ) ); }
     2371                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::One ); }
    24212372        ;
    24222373
     
    24742425type_type_specifier:                                                                    // typedef types
    24752426        type_name
    2476                 { $$ = DeclarationNode::newFromTypeData( $1 ); }
    24772427        | type_qualifier_list type_name
    2478                 { $$ = DeclarationNode::newFromTypeData( $2 )->addQualifiers( $1 ); }
     2428                { $$ = $2->addQualifiers( $1 ); }
    24792429        | type_type_specifier type_qualifier
    24802430                { $$ = $1->addQualifiers( $2 ); }
     
    24832433type_name:
    24842434        TYPEDEFname
    2485                 { $$ = build_typedef( $1 ); }
     2435                { $$ = DeclarationNode::newFromTypedef( $1 ); }
    24862436        | '.' TYPEDEFname
    2487                 { $$ = build_qualified_type( build_global_scope(), build_typedef( $2 ) ); }
     2437                { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), DeclarationNode::newFromTypedef( $2 ) ); }
    24882438        | type_name '.' TYPEDEFname
    2489                 { $$ = build_qualified_type( $1, build_typedef( $3 ) ); }
     2439                { $$ = DeclarationNode::newQualifiedType( $1, DeclarationNode::newFromTypedef( $3 ) ); }
    24902440        | typegen_name
    24912441        | '.' typegen_name
    2492                 { $$ = build_qualified_type( build_global_scope(), $2 ); }
     2442                { $$ = DeclarationNode::newQualifiedType( DeclarationNode::newFromGlobalScope(), $2 ); }
    24932443        | type_name '.' typegen_name
    2494                 { $$ = build_qualified_type( $1, $3 ); }
     2444                { $$ = DeclarationNode::newQualifiedType( $1, $3 ); }
    24952445        ;
    24962446
    24972447typegen_name:                                                                                   // CFA
    24982448        TYPEGENname
    2499                 { $$ = build_type_gen( $1, nullptr ); }
     2449                { $$ = DeclarationNode::newFromTypeGen( $1, nullptr ); }
    25002450        | TYPEGENname '(' ')'
    2501                 { $$ = build_type_gen( $1, nullptr ); }
     2451                { $$ = DeclarationNode::newFromTypeGen( $1, nullptr ); }
    25022452        | TYPEGENname '(' type_list ')'
    2503                 { $$ = build_type_gen( $1, $3 ); }
     2453                { $$ = DeclarationNode::newFromTypeGen( $1, $3 ); }
    25042454        ;
    25052455
     
    25132463        | enum_type_nobody
    25142464        ;
    2515 
    2516 // ************************** AGGREGATE *******************************
    25172465
    25182466aggregate_type:                                                                                 // struct, union
     
    25372485          '{' field_declaration_list_opt '}' type_parameters_opt
    25382486                {
    2539                         DeclarationNode::newFromTypeData( build_typedef( $3 ) );
     2487                        DeclarationNode::newFromTypedef( $3 );
    25402488                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
    25412489                }
     
    25472495          '{' field_declaration_list_opt '}' type_parameters_opt
    25482496                {
    2549                         DeclarationNode::newFromTypeData( build_type_gen( $3, nullptr ) );
     2497                        DeclarationNode::newFromTypeGen( $3, nullptr );
    25502498                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
    25512499                }
     
    25722520                        // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is
    25732521                        // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and
    2574                         if ( $3->kind == TypeData::SymbolicInst && ! $3->symbolic.isTypedef ) {
    2575                                 $$ = DeclarationNode::newFromTypeData( $3 )->addQualifiers( $2 );
     2522                        // delete newFromTypeGen.
     2523                        if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) {
     2524                                $$ = $3->addQualifiers( $2 );
    25762525                        } else {
    2577                                 $$ = DeclarationNode::newAggregate( $1, $3->symbolic.name, $3->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
    2578                                 $3->symbolic.name = nullptr;                    // copied to $$
    2579                                 $3->symbolic.actuals = nullptr;
     2526                                $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
     2527                                $3->type->symbolic.name = nullptr;                      // copied to $$
     2528                                $3->type->symbolic.actuals = nullptr;
    25802529                                delete $3;
    25812530                        }
     
    25952544        | EXCEPTION                                                                                     // CFA
    25962545                { $$ = ast::AggregateDecl::Exception; }
     2546          //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; }
    25972547        ;
    25982548
     
    27332683        ;
    27342684
    2735 // ************************** ENUMERATION *******************************
     2685// ***********
     2686// Enumeration
     2687// ***********
    27362688
    27372689enum_type:
     
    28022754        | ENUM attribute_list_opt type_name
    28032755                {
    2804                         typedefTable.makeTypedef( *$3->symbolic.name, "enum_type_nobody 2" );
    2805                         $$ = DeclarationNode::newEnum( $3->symbolic.name, nullptr, false, false )->addQualifiers( $2 );
     2756                        typedefTable.makeTypedef( *$3->type->symbolic.name, "enum_type_nobody 2" );
     2757                        $$ = DeclarationNode::newEnum( $3->type->symbolic.name, nullptr, false, false )->addQualifiers( $2 );
    28062758                }
    28072759        ;
     
    28112763                { $$ = DeclarationNode::newEnumValueGeneric( $2, $3 ); }
    28122764        | INLINE type_name
    2813                 { $$ = DeclarationNode::newEnumInLine( *$2->symbolic.name ); }
     2765                { $$ = DeclarationNode::newEnumInLine( *$2->type->symbolic.name ); }
    28142766        | enumerator_list ',' visible_hide_opt identifier_or_type_name enumerator_value_opt
    28152767                { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
     
    28332785        ;
    28342786
    2835 // ************************** FUNCTION PARAMETERS *******************************
     2787// *******************
     2788// Function parameters
     2789// *******************
    28362790
    28372791parameter_list_ellipsis_opt:
     
    28562810cfa_parameter_list_ellipsis_opt:                                                // CFA, abstract + real
    28572811        // empty
    2858                 { $$ = DeclarationNode::newFromTypeData( build_basic_type( DeclarationNode::Void ) ); }
     2812                { $$ = DeclarationNode::newBasicType( DeclarationNode::Void ); }
    28592813        | ELLIPSIS
    28602814                { $$ = nullptr; }
     
    29142868        | type_qualifier_list cfa_abstract_tuple identifier_or_type_name default_initializer_opt
    29152869                { $$ = $2->addName( $3 )->addQualifiers( $1 ); }
    2916         | cfa_function_specifier                                                        // int f( "int fp()" );
     2870        | cfa_function_specifier
    29172871        ;
    29182872
     
    29242878        | type_qualifier_list cfa_abstract_tuple
    29252879                { $$ = $2->addQualifiers( $1 ); }
    2926         | cfa_abstract_function                                                         // int f( "int ()" );
     2880        | cfa_abstract_function
    29272881        ;
    29282882
     
    29742928        | initializer
    29752929        | designation initializer                                       { $$ = $2->set_designators( $1 ); }
    2976         | initializer_list_opt ',' initializer          { $$ = $1->set_last( $3 ); }
    2977         | initializer_list_opt ',' designation initializer { $$ = $1->set_last( $4->set_designators( $3 ) ); }
     2930        | initializer_list_opt ',' initializer          { $$ = (InitializerNode *)( $1->set_last( $3 ) ); }
     2931        | initializer_list_opt ',' designation initializer { $$ = (InitializerNode *)($1->set_last( $4->set_designators( $3 ) )); }
    29782932        ;
    29792933
     
    29972951        designator
    29982952        | designator_list designator
    2999                 { $$ = $1->set_last( $2 ); }
     2953                { $$ = (ExpressionNode *)($1->set_last( $2 )); }
    30002954        //| designator_list designator                                          { $$ = new ExpressionNode( $1, $2 ); }
    30012955        ;
     
    30823036                { $$ = ast::TypeDecl::Dtype; }
    30833037        | '*'
    3084                 { $$ = ast::TypeDecl::DStype; }                                 // Dtype + sized
    3085         // | '(' '*' ')'                                                                        // Gregor made me do it
    3086         //      { $$ = ast::TypeDecl::Ftype; }
     3038                { $$ = ast::TypeDecl::DStype; }                                         // dtype + sized
     3039        // | '(' '*' ')'
     3040        //      { $$ = ast::TypeDecl::Ftype; }
    30873041        | ELLIPSIS
    30883042                { $$ = ast::TypeDecl::Ttype; }
     
    31263080        | assignment_expression
    31273081        | type_list ',' type
    3128                 { $$ = $1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) ); }
     3082                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    31293083        | type_list ',' assignment_expression
    3130                 { $$ = $1->set_last( $3 ); }
     3084                { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
    31313085        ;
    31323086
     
    32903244                        $$ = $6;
    32913245                }
    3292                 // global distribution
     3246        // global distribution
    32933247        | type_qualifier_list
    32943248                {
     
    34153369        ;
    34163370
    3417 // **************************** ASM *****************************
    3418 
    34193371asm_name_opt:                                                                                   // GCC
    34203372        // empty
     
    34273379                }
    34283380        ;
    3429 
    3430 // **************************** ATTRIBUTE *****************************
    34313381
    34323382attribute_list_opt:                                                                             // GCC
     
    37923742                { $$ = $1->addQualifiers( $2 ); }
    37933743        | '&' MUTEX paren_identifier attribute_list_opt
    3794                 { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newFromTypeData( build_type_qualifier( ast::CV::Mutex ) ),
     3744                { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ),
    37953745                                                                                                                        OperKinds::AddressOf ) )->addQualifiers( $4 ); }
    37963746        | identifier_parameter_ptr
     
    38433793                { $$ = $1->addQualifiers( $2 ); }
    38443794        | '&' MUTEX typedef_name attribute_list_opt
    3845                 { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newFromTypeData( build_type_qualifier( ast::CV::Mutex ) ),
     3795                { $$ = $3->addPointer( DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ),
    38463796                                                                                                                        OperKinds::AddressOf ) )->addQualifiers( $4 ); }
    38473797        | type_parameter_ptr
     
    38763826
    38773827type_parameter_function:
    3878         typedef_name '(' parameter_list_ellipsis_opt ')'        // empty parameter list OBSOLESCENT (see 3)
     3828        typedef_name '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
    38793829                { $$ = $1->addParamList( $3 ); }
    38803830        | '(' type_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
     
    39263876
    39273877abstract_function:
    3928         '(' parameter_list_ellipsis_opt ')'                                     // empty parameter list OBSOLESCENT (see 3)
     3878        '(' parameter_list_ellipsis_opt ')'                     // empty parameter list OBSOLESCENT (see 3)
    39293879                { $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
    39303880        | '(' abstract_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
     
    39653915        | assignment_expression upupeq assignment_expression
    39663916        | array_type_list ',' basic_type_name
    3967                 { $$ = $1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) ); }
     3917                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    39683918        | array_type_list ',' type_name
    3969                 { $$ = $1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) ); }
     3919                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    39703920        | array_type_list ',' assignment_expression upupeq assignment_expression
    39713921        ;
     
    40273977        abstract_parameter_ptr
    40283978        | '&' MUTEX attribute_list_opt
    4029                 { $$ = DeclarationNode::newPointer( DeclarationNode::newFromTypeData( build_type_qualifier( ast::CV::Mutex ) ), OperKinds::AddressOf )->addQualifiers( $3 ); }
     3979                { $$ = DeclarationNode::newPointer( DeclarationNode::newTypeQualifier( ast::CV::Mutex ), OperKinds::AddressOf )->addQualifiers( $3 ); }
    40303980        | abstract_parameter_array attribute_list_opt
    40313981                { $$ = $1->addQualifiers( $2 ); }
     
    40584008
    40594009abstract_parameter_function:
    4060         '(' parameter_list_ellipsis_opt ')'                                     // empty parameter list OBSOLESCENT (see 3)
     4010        '(' parameter_list_ellipsis_opt ')'                     // empty parameter list OBSOLESCENT (see 3)
    40614011                { $$ = DeclarationNode::newFunction( nullptr, nullptr, $2, nullptr ); }
    40624012        | '(' abstract_parameter_ptr ')' '(' parameter_list_ellipsis_opt ')' // empty parameter list OBSOLESCENT (see 3)
     
    43304280// mode: c++ //
    43314281// tab-width: 4 //
    4332 // compile-command: "bison -Wcounterexamples parser.yy" //
     4282// compile-command: "make install" //
    43334283// End: //
  • tests/.expect/functions.arm64.txt

    r03606ce r06601401  
    9494    __attribute__ ((unused)) const signed int _X11_retval_fO5Ki_1;
    9595}
    96 void _X1fFv___1(void);
    97 void _X1fFv___1(void);
    9896signed int _X1fFi___1(void);
    99 void _X1fFv_i__1(signed int __anonymous_object4);
    100 void _X1fFv_i__1(signed int __anonymous_object5);
    101 signed int _X1fFi_i__1(signed int __anonymous_object6);
    102 void _X1fFv___1(void){
    103 }
    104 void _X2fvFv___1(void){
    105 }
     97signed int _X1fFi_i__1(signed int __anonymous_object4);
    10698signed int _X1fFi___1(void){
    10799    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    108100}
    109 void _X1fFv_i__1(__attribute__ ((unused)) signed int __anonymous_object7){
    110 }
    111 void _X2fvFv_i__1(__attribute__ ((unused)) signed int __anonymous_object8){
    112 }
    113 signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object9){
     101signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object5){
    114102    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    115103}
    116104signed int _X1fFi___1(void);
    117 void _X1fFv_i__1(signed int _X1xi_1);
    118 void _X2fvFv_i__1(signed int _X1xi_1);
    119 void _X2f2Fv_i__1(signed int _X1xi_1){
    120 }
    121 void _X3fv1Fv_i__1(signed int _X1xi_1){
    122 }
    123105struct _tuple2_ {
    124106};
     
    145127};
    146128struct _conc__tuple2_0 _X1fFT2ii___1(void);
    147 void _X1fFv_ii__1(signed int __anonymous_object10, signed int _X1xi_1);
    148 void _X2fvFv_ii__1(signed int __anonymous_object11, signed int _X1xi_1);
    149 struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object12, signed int _X1xi_1);
     129struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object6, signed int _X1xi_1);
    150130struct _conc__tuple2_0 _X1fFT2ii___1(void){
    151131    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    152132}
    153 void _X1fFv_ii__1(__attribute__ ((unused)) signed int __anonymous_object13, signed int _X1xi_1){
    154 }
    155 void _X2fvFv_ii__1(__attribute__ ((unused)) signed int __anonymous_object14, signed int _X1xi_1){
    156 }
    157 struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object15, signed int _X1xi_1){
     133struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object7, signed int _X1xi_1){
    158134    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    159135}
     
    189165};
    190166struct _conc__tuple3_1 _X1fFT3iii___1(void);
    191 void _X1fFv_iii__1(signed int __anonymous_object16, signed int _X1xi_1, signed int __anonymous_object17);
    192 void _X2fvFv_iii__1(signed int __anonymous_object18, signed int _X1xi_1, signed int __anonymous_object19);
    193 struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object20, signed int _X1xi_1, signed int __anonymous_object21);
     167struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object8, signed int _X1xi_1, signed int __anonymous_object9);
    194168struct _conc__tuple3_1 _X1fFT3iii___1(void){
    195169    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    196170}
    197 void _X1fFv_iii__1(__attribute__ ((unused)) signed int __anonymous_object22, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object23){
    198 }
    199 void _X2fvFv_iii__1(__attribute__ ((unused)) signed int __anonymous_object24, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object25){
    200 }
    201 struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object26, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object27){
     171struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object10, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object11){
    202172    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    203173}
     
    209179};
    210180struct _conc__tuple3_2 _X1fFT3iiPi___1(void);
    211 void _X1fFv_iiPi__1(signed int __anonymous_object28, signed int _X1xi_1, signed int *_X1yPi_1);
    212 void _X2fvFv_iiPi__1(signed int __anonymous_object29, signed int _X1xi_1, signed int *_X1yPi_1);
    213 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object30, signed int _X1xi_1, signed int *_X1yPi_1);
     181struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object12, signed int _X1xi_1, signed int *_X1yPi_1);
    214182struct _conc__tuple3_2 _X1fFT3iiPi___1(void){
    215183    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    216184}
    217 void _X1fFv_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object31, signed int _X1xi_1, signed int *_X1yPi_1){
    218 }
    219 void _X2fvFv_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object32, signed int _X1xi_1, signed int *_X1yPi_1){
    220 }
    221 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object33, signed int _X1xi_1, signed int *_X1yPi_1){
     185struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object13, signed int _X1xi_1, signed int *_X1yPi_1){
    222186    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    223187}
    224 signed int _X3f11Fi_i__1(signed int __anonymous_object34);
     188signed int _X3f11Fi_i__1(signed int __anonymous_object14);
    225189signed int _X3f12Fi___1(void);
    226190const double _X4bar1Fd___1();
    227 const double _X4bar2Fd_i__1(signed int __anonymous_object35);
    228 const double _X4bar3Fd_d__1(double __anonymous_object36);
     191const double _X4bar2Fd_i__1(signed int __anonymous_object15);
     192const double _X4bar3Fd_d__1(double __anonymous_object16);
    229193const double _X3fooFd___1(void);
    230 const double _X3fooFd_i__1(signed int __anonymous_object37);
    231 const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object38){
     194const double _X3fooFd_i__1(signed int __anonymous_object17);
     195const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object18){
    232196    __attribute__ ((unused)) const double _X11_retval_fooKd_1;
    233197    {
     
    281245
    282246}
    283 struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object39){
     247struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object19){
    284248    __attribute__ ((unused)) struct S _X11_retval_rtnS1S_1;
    285249}
    286 signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object40)(signed int __param_0, signed int __param_1), __attribute__ ((unused)) signed int (*__anonymous_object41)(signed int __param_0)){
     250signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object20)(signed int __param_0, signed int __param_1), __attribute__ ((unused)) signed int (*__anonymous_object21)(signed int __param_0)){
    287251    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    288252    signed int (*(*_X2pcPA0A0PA0A0i_2)[][((unsigned long int )10)])[][((unsigned long int )3)];
     
    310274    __attribute__ ((unused)) const struct _conc__tuple2_3 _X10_retval_f5KT2PiKi_1;
    311275}
    312 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object42)(), signed int *(*__anonymous_object43)(), signed int **(*__anonymous_object44)(), signed int *const *(*__anonymous_object45)(), signed int *const *const (*__anonymous_object46)(), signed int *__anonymous_object47, signed int __anonymous_object48[10], signed int **__anonymous_object49, signed int *__anonymous_object50[10], signed int ***__anonymous_object51, signed int **__anonymous_object52[10], signed int *const **__anonymous_object53, signed int *const *__anonymous_object54[10], signed int *const *const *__anonymous_object55, signed int *const *const __anonymous_object56[10]);
    313 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object57)(), __attribute__ ((unused)) signed int *(*__anonymous_object58)(), __attribute__ ((unused)) signed int **(*__anonymous_object59)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object60)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object61)(), __attribute__ ((unused)) signed int *__anonymous_object62, __attribute__ ((unused)) signed int __anonymous_object63[10], __attribute__ ((unused)) signed int **__anonymous_object64, __attribute__ ((unused)) signed int *__anonymous_object65[10], __attribute__ ((unused)) signed int ***__anonymous_object66, __attribute__ ((unused)) signed int **__anonymous_object67[10], __attribute__ ((unused)) signed int *const **__anonymous_object68, __attribute__ ((unused)) signed int *const *__anonymous_object69[10], __attribute__ ((unused)) signed int *const *const *__anonymous_object70, __attribute__ ((unused)) signed int *const *const __anonymous_object71[10]){
     276signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object22)(), signed int *(*__anonymous_object23)(), signed int **(*__anonymous_object24)(), signed int *const *(*__anonymous_object25)(), signed int *const *const (*__anonymous_object26)(), signed int *__anonymous_object27, signed int __anonymous_object28[10], signed int **__anonymous_object29, signed int *__anonymous_object30[10], signed int ***__anonymous_object31, signed int **__anonymous_object32[10], signed int *const **__anonymous_object33, signed int *const *__anonymous_object34[10], signed int *const *const *__anonymous_object35, signed int *const *const __anonymous_object36[10]);
     277signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object37)(), __attribute__ ((unused)) signed int *(*__anonymous_object38)(), __attribute__ ((unused)) signed int **(*__anonymous_object39)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object40)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object41)(), __attribute__ ((unused)) signed int *__anonymous_object42, __attribute__ ((unused)) signed int __anonymous_object43[10], __attribute__ ((unused)) signed int **__anonymous_object44, __attribute__ ((unused)) signed int *__anonymous_object45[10], __attribute__ ((unused)) signed int ***__anonymous_object46, __attribute__ ((unused)) signed int **__anonymous_object47[10], __attribute__ ((unused)) signed int *const **__anonymous_object48, __attribute__ ((unused)) signed int *const *__anonymous_object49[10], __attribute__ ((unused)) signed int *const *const *__anonymous_object50, __attribute__ ((unused)) signed int *const *const __anonymous_object51[10]){
    314278    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    315279}
  • tests/.expect/functions.x64.txt

    r03606ce r06601401  
    9494    __attribute__ ((unused)) const signed int _X11_retval_fO5Ki_1;
    9595}
    96 void _X1fFv___1(void);
    97 void _X1fFv___1(void);
    9896signed int _X1fFi___1(void);
    99 void _X1fFv_i__1(signed int __anonymous_object4);
    100 void _X1fFv_i__1(signed int __anonymous_object5);
    101 signed int _X1fFi_i__1(signed int __anonymous_object6);
    102 void _X1fFv___1(void){
    103 }
    104 void _X2fvFv___1(void){
    105 }
     97signed int _X1fFi_i__1(signed int __anonymous_object4);
    10698signed int _X1fFi___1(void){
    10799    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    108100}
    109 void _X1fFv_i__1(__attribute__ ((unused)) signed int __anonymous_object7){
    110 }
    111 void _X2fvFv_i__1(__attribute__ ((unused)) signed int __anonymous_object8){
    112 }
    113 signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object9){
     101signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object5){
    114102    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    115103}
    116104signed int _X1fFi___1(void);
    117 void _X1fFv_i__1(signed int _X1xi_1);
    118 void _X2fvFv_i__1(signed int _X1xi_1);
    119 void _X2f2Fv_i__1(signed int _X1xi_1){
    120 }
    121 void _X3fv1Fv_i__1(signed int _X1xi_1){
    122 }
    123105struct _tuple2_ {
    124106};
     
    145127};
    146128struct _conc__tuple2_0 _X1fFT2ii___1(void);
    147 void _X1fFv_ii__1(signed int __anonymous_object10, signed int _X1xi_1);
    148 void _X2fvFv_ii__1(signed int __anonymous_object11, signed int _X1xi_1);
    149 struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object12, signed int _X1xi_1);
     129struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object6, signed int _X1xi_1);
    150130struct _conc__tuple2_0 _X1fFT2ii___1(void){
    151131    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    152132}
    153 void _X1fFv_ii__1(__attribute__ ((unused)) signed int __anonymous_object13, signed int _X1xi_1){
    154 }
    155 void _X2fvFv_ii__1(__attribute__ ((unused)) signed int __anonymous_object14, signed int _X1xi_1){
    156 }
    157 struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object15, signed int _X1xi_1){
     133struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object7, signed int _X1xi_1){
    158134    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    159135}
     
    189165};
    190166struct _conc__tuple3_1 _X1fFT3iii___1(void);
    191 void _X1fFv_iii__1(signed int __anonymous_object16, signed int _X1xi_1, signed int __anonymous_object17);
    192 void _X2fvFv_iii__1(signed int __anonymous_object18, signed int _X1xi_1, signed int __anonymous_object19);
    193 struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object20, signed int _X1xi_1, signed int __anonymous_object21);
     167struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object8, signed int _X1xi_1, signed int __anonymous_object9);
    194168struct _conc__tuple3_1 _X1fFT3iii___1(void){
    195169    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    196170}
    197 void _X1fFv_iii__1(__attribute__ ((unused)) signed int __anonymous_object22, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object23){
    198 }
    199 void _X2fvFv_iii__1(__attribute__ ((unused)) signed int __anonymous_object24, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object25){
    200 }
    201 struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object26, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object27){
     171struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object10, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object11){
    202172    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    203173}
     
    209179};
    210180struct _conc__tuple3_2 _X1fFT3iiPi___1(void);
    211 void _X1fFv_iiPi__1(signed int __anonymous_object28, signed int _X1xi_1, signed int *_X1yPi_1);
    212 void _X2fvFv_iiPi__1(signed int __anonymous_object29, signed int _X1xi_1, signed int *_X1yPi_1);
    213 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object30, signed int _X1xi_1, signed int *_X1yPi_1);
     181struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object12, signed int _X1xi_1, signed int *_X1yPi_1);
    214182struct _conc__tuple3_2 _X1fFT3iiPi___1(void){
    215183    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    216184}
    217 void _X1fFv_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object31, signed int _X1xi_1, signed int *_X1yPi_1){
    218 }
    219 void _X2fvFv_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object32, signed int _X1xi_1, signed int *_X1yPi_1){
    220 }
    221 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object33, signed int _X1xi_1, signed int *_X1yPi_1){
     185struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object13, signed int _X1xi_1, signed int *_X1yPi_1){
    222186    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    223187}
    224 signed int _X3f11Fi_i__1(signed int __anonymous_object34);
     188signed int _X3f11Fi_i__1(signed int __anonymous_object14);
    225189signed int _X3f12Fi___1(void);
    226190const double _X4bar1Fd___1();
    227 const double _X4bar2Fd_i__1(signed int __anonymous_object35);
    228 const double _X4bar3Fd_d__1(double __anonymous_object36);
     191const double _X4bar2Fd_i__1(signed int __anonymous_object15);
     192const double _X4bar3Fd_d__1(double __anonymous_object16);
    229193const double _X3fooFd___1(void);
    230 const double _X3fooFd_i__1(signed int __anonymous_object37);
    231 const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object38){
     194const double _X3fooFd_i__1(signed int __anonymous_object17);
     195const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object18){
    232196    __attribute__ ((unused)) const double _X11_retval_fooKd_1;
    233197    {
     
    281245
    282246}
    283 struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object39){
     247struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object19){
    284248    __attribute__ ((unused)) struct S _X11_retval_rtnS1S_1;
    285249}
    286 signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object40)(signed int __param_0, signed int __param_1), __attribute__ ((unused)) signed int (*__anonymous_object41)(signed int __param_0)){
     250signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object20)(signed int __param_0, signed int __param_1), __attribute__ ((unused)) signed int (*__anonymous_object21)(signed int __param_0)){
    287251    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    288252    signed int (*(*_X2pcPA0A0PA0A0i_2)[][((unsigned long int )10)])[][((unsigned long int )3)];
     
    310274    __attribute__ ((unused)) const struct _conc__tuple2_3 _X10_retval_f5KT2PiKi_1;
    311275}
    312 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object42)(), signed int *(*__anonymous_object43)(), signed int **(*__anonymous_object44)(), signed int *const *(*__anonymous_object45)(), signed int *const *const (*__anonymous_object46)(), signed int *__anonymous_object47, signed int __anonymous_object48[10], signed int **__anonymous_object49, signed int *__anonymous_object50[10], signed int ***__anonymous_object51, signed int **__anonymous_object52[10], signed int *const **__anonymous_object53, signed int *const *__anonymous_object54[10], signed int *const *const *__anonymous_object55, signed int *const *const __anonymous_object56[10]);
    313 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object57)(), __attribute__ ((unused)) signed int *(*__anonymous_object58)(), __attribute__ ((unused)) signed int **(*__anonymous_object59)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object60)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object61)(), __attribute__ ((unused)) signed int *__anonymous_object62, __attribute__ ((unused)) signed int __anonymous_object63[10], __attribute__ ((unused)) signed int **__anonymous_object64, __attribute__ ((unused)) signed int *__anonymous_object65[10], __attribute__ ((unused)) signed int ***__anonymous_object66, __attribute__ ((unused)) signed int **__anonymous_object67[10], __attribute__ ((unused)) signed int *const **__anonymous_object68, __attribute__ ((unused)) signed int *const *__anonymous_object69[10], __attribute__ ((unused)) signed int *const *const *__anonymous_object70, __attribute__ ((unused)) signed int *const *const __anonymous_object71[10]){
     276signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object22)(), signed int *(*__anonymous_object23)(), signed int **(*__anonymous_object24)(), signed int *const *(*__anonymous_object25)(), signed int *const *const (*__anonymous_object26)(), signed int *__anonymous_object27, signed int __anonymous_object28[10], signed int **__anonymous_object29, signed int *__anonymous_object30[10], signed int ***__anonymous_object31, signed int **__anonymous_object32[10], signed int *const **__anonymous_object33, signed int *const *__anonymous_object34[10], signed int *const *const *__anonymous_object35, signed int *const *const __anonymous_object36[10]);
     277signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object37)(), __attribute__ ((unused)) signed int *(*__anonymous_object38)(), __attribute__ ((unused)) signed int **(*__anonymous_object39)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object40)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object41)(), __attribute__ ((unused)) signed int *__anonymous_object42, __attribute__ ((unused)) signed int __anonymous_object43[10], __attribute__ ((unused)) signed int **__anonymous_object44, __attribute__ ((unused)) signed int *__anonymous_object45[10], __attribute__ ((unused)) signed int ***__anonymous_object46, __attribute__ ((unused)) signed int **__anonymous_object47[10], __attribute__ ((unused)) signed int *const **__anonymous_object48, __attribute__ ((unused)) signed int *const *__anonymous_object49[10], __attribute__ ((unused)) signed int *const *const *__anonymous_object50, __attribute__ ((unused)) signed int *const *const __anonymous_object51[10]){
    314278    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    315279}
  • tests/.expect/functions.x86.txt

    r03606ce r06601401  
    9494    __attribute__ ((unused)) const signed int _X11_retval_fO5Ki_1;
    9595}
    96 void _X1fFv___1(void);
    97 void _X1fFv___1(void);
    9896signed int _X1fFi___1(void);
    99 void _X1fFv_i__1(signed int __anonymous_object4);
    100 void _X1fFv_i__1(signed int __anonymous_object5);
    101 signed int _X1fFi_i__1(signed int __anonymous_object6);
    102 void _X1fFv___1(void){
    103 }
    104 void _X2fvFv___1(void){
    105 }
     97signed int _X1fFi_i__1(signed int __anonymous_object4);
    10698signed int _X1fFi___1(void){
    10799    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    108100}
    109 void _X1fFv_i__1(__attribute__ ((unused)) signed int __anonymous_object7){
    110 }
    111 void _X2fvFv_i__1(__attribute__ ((unused)) signed int __anonymous_object8){
    112 }
    113 signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object9){
     101signed int _X1fFi_i__1(__attribute__ ((unused)) signed int __anonymous_object5){
    114102    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    115103}
    116104signed int _X1fFi___1(void);
    117 void _X1fFv_i__1(signed int _X1xi_1);
    118 void _X2fvFv_i__1(signed int _X1xi_1);
    119 void _X2f2Fv_i__1(signed int _X1xi_1){
    120 }
    121 void _X3fv1Fv_i__1(signed int _X1xi_1){
    122 }
    123105struct _tuple2_ {
    124106};
     
    145127};
    146128struct _conc__tuple2_0 _X1fFT2ii___1(void);
    147 void _X1fFv_ii__1(signed int __anonymous_object10, signed int _X1xi_1);
    148 void _X2fvFv_ii__1(signed int __anonymous_object11, signed int _X1xi_1);
    149 struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object12, signed int _X1xi_1);
     129struct _conc__tuple2_0 _X1fFT2ii_ii__1(signed int __anonymous_object6, signed int _X1xi_1);
    150130struct _conc__tuple2_0 _X1fFT2ii___1(void){
    151131    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    152132}
    153 void _X1fFv_ii__1(__attribute__ ((unused)) signed int __anonymous_object13, signed int _X1xi_1){
    154 }
    155 void _X2fvFv_ii__1(__attribute__ ((unused)) signed int __anonymous_object14, signed int _X1xi_1){
    156 }
    157 struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object15, signed int _X1xi_1){
     133struct _conc__tuple2_0 _X1fFT2ii_ii__1(__attribute__ ((unused)) signed int __anonymous_object7, signed int _X1xi_1){
    158134    __attribute__ ((unused)) struct _conc__tuple2_0 _X9_retval_fT2ii_1 = {  };
    159135}
     
    189165};
    190166struct _conc__tuple3_1 _X1fFT3iii___1(void);
    191 void _X1fFv_iii__1(signed int __anonymous_object16, signed int _X1xi_1, signed int __anonymous_object17);
    192 void _X2fvFv_iii__1(signed int __anonymous_object18, signed int _X1xi_1, signed int __anonymous_object19);
    193 struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object20, signed int _X1xi_1, signed int __anonymous_object21);
     167struct _conc__tuple3_1 _X1fFT3iii_iii__1(signed int __anonymous_object8, signed int _X1xi_1, signed int __anonymous_object9);
    194168struct _conc__tuple3_1 _X1fFT3iii___1(void){
    195169    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    196170}
    197 void _X1fFv_iii__1(__attribute__ ((unused)) signed int __anonymous_object22, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object23){
    198 }
    199 void _X2fvFv_iii__1(__attribute__ ((unused)) signed int __anonymous_object24, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object25){
    200 }
    201 struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object26, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object27){
     171struct _conc__tuple3_1 _X1fFT3iii_iii__1(__attribute__ ((unused)) signed int __anonymous_object10, signed int _X1xi_1, __attribute__ ((unused)) signed int __anonymous_object11){
    202172    __attribute__ ((unused)) struct _conc__tuple3_1 _X9_retval_fT3iii_1 = {  };
    203173}
     
    209179};
    210180struct _conc__tuple3_2 _X1fFT3iiPi___1(void);
    211 void _X1fFv_iiPi__1(signed int __anonymous_object28, signed int _X1xi_1, signed int *_X1yPi_1);
    212 void _X2fvFv_iiPi__1(signed int __anonymous_object29, signed int _X1xi_1, signed int *_X1yPi_1);
    213 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object30, signed int _X1xi_1, signed int *_X1yPi_1);
     181struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(signed int __anonymous_object12, signed int _X1xi_1, signed int *_X1yPi_1);
    214182struct _conc__tuple3_2 _X1fFT3iiPi___1(void){
    215183    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    216184}
    217 void _X1fFv_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object31, signed int _X1xi_1, signed int *_X1yPi_1){
    218 }
    219 void _X2fvFv_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object32, signed int _X1xi_1, signed int *_X1yPi_1){
    220 }
    221 struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object33, signed int _X1xi_1, signed int *_X1yPi_1){
     185struct _conc__tuple3_2 _X1fFT3iiPi_iiPi__1(__attribute__ ((unused)) signed int __anonymous_object13, signed int _X1xi_1, signed int *_X1yPi_1){
    222186    __attribute__ ((unused)) struct _conc__tuple3_2 _X9_retval_fT3iiPi_1 = {  };
    223187}
    224 signed int _X3f11Fi_i__1(signed int __anonymous_object34);
     188signed int _X3f11Fi_i__1(signed int __anonymous_object14);
    225189signed int _X3f12Fi___1(void);
    226190const double _X4bar1Fd___1();
    227 const double _X4bar2Fd_i__1(signed int __anonymous_object35);
    228 const double _X4bar3Fd_d__1(double __anonymous_object36);
     191const double _X4bar2Fd_i__1(signed int __anonymous_object15);
     192const double _X4bar3Fd_d__1(double __anonymous_object16);
    229193const double _X3fooFd___1(void);
    230 const double _X3fooFd_i__1(signed int __anonymous_object37);
    231 const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object38){
     194const double _X3fooFd_i__1(signed int __anonymous_object17);
     195const double _X3fooFd_d__1(__attribute__ ((unused)) double __anonymous_object18){
    232196    __attribute__ ((unused)) const double _X11_retval_fooKd_1;
    233197    {
     
    281245
    282246}
    283 struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object39){
     247struct S _X3rtnFS1S_i__1(__attribute__ ((unused)) signed int __anonymous_object19){
    284248    __attribute__ ((unused)) struct S _X11_retval_rtnS1S_1;
    285249}
    286 signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object40)(signed int __param_0, signed int __param_1), __attribute__ ((unused)) signed int (*__anonymous_object41)(signed int __param_0)){
     250signed int _X1fFi_Fi_ii_Fi_i___1(__attribute__ ((unused)) signed int (*__anonymous_object20)(signed int __param_0, signed int __param_1), __attribute__ ((unused)) signed int (*__anonymous_object21)(signed int __param_0)){
    287251    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    288252    signed int (*(*_X2pcPA0A0PA0A0i_2)[][((unsigned int )10)])[][((unsigned int )3)];
     
    310274    __attribute__ ((unused)) const struct _conc__tuple2_3 _X10_retval_f5KT2PiKi_1;
    311275}
    312 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object42)(), signed int *(*__anonymous_object43)(), signed int **(*__anonymous_object44)(), signed int *const *(*__anonymous_object45)(), signed int *const *const (*__anonymous_object46)(), signed int *__anonymous_object47, signed int __anonymous_object48[10], signed int **__anonymous_object49, signed int *__anonymous_object50[10], signed int ***__anonymous_object51, signed int **__anonymous_object52[10], signed int *const **__anonymous_object53, signed int *const *__anonymous_object54[10], signed int *const *const *__anonymous_object55, signed int *const *const __anonymous_object56[10]);
    313 signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object57)(), __attribute__ ((unused)) signed int *(*__anonymous_object58)(), __attribute__ ((unused)) signed int **(*__anonymous_object59)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object60)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object61)(), __attribute__ ((unused)) signed int *__anonymous_object62, __attribute__ ((unused)) signed int __anonymous_object63[10], __attribute__ ((unused)) signed int **__anonymous_object64, __attribute__ ((unused)) signed int *__anonymous_object65[10], __attribute__ ((unused)) signed int ***__anonymous_object66, __attribute__ ((unused)) signed int **__anonymous_object67[10], __attribute__ ((unused)) signed int *const **__anonymous_object68, __attribute__ ((unused)) signed int *const *__anonymous_object69[10], __attribute__ ((unused)) signed int *const *const *__anonymous_object70, __attribute__ ((unused)) signed int *const *const __anonymous_object71[10]){
     276signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(signed int (*__anonymous_object22)(), signed int *(*__anonymous_object23)(), signed int **(*__anonymous_object24)(), signed int *const *(*__anonymous_object25)(), signed int *const *const (*__anonymous_object26)(), signed int *__anonymous_object27, signed int __anonymous_object28[10], signed int **__anonymous_object29, signed int *__anonymous_object30[10], signed int ***__anonymous_object31, signed int **__anonymous_object32[10], signed int *const **__anonymous_object33, signed int *const *__anonymous_object34[10], signed int *const *const *__anonymous_object35, signed int *const *const __anonymous_object36[10]);
     277signed int _X1fFi_Fi__FPi__FPPi__FPKPi__FPKPi__PiPiPPiPPiPPPiPPPiPPKPiPPKPiPKPKPiPKPKPi__1(__attribute__ ((unused)) signed int (*__anonymous_object37)(), __attribute__ ((unused)) signed int *(*__anonymous_object38)(), __attribute__ ((unused)) signed int **(*__anonymous_object39)(), __attribute__ ((unused)) signed int *const *(*__anonymous_object40)(), __attribute__ ((unused)) signed int *const *const (*__anonymous_object41)(), __attribute__ ((unused)) signed int *__anonymous_object42, __attribute__ ((unused)) signed int __anonymous_object43[10], __attribute__ ((unused)) signed int **__anonymous_object44, __attribute__ ((unused)) signed int *__anonymous_object45[10], __attribute__ ((unused)) signed int ***__anonymous_object46, __attribute__ ((unused)) signed int **__anonymous_object47[10], __attribute__ ((unused)) signed int *const **__anonymous_object48, __attribute__ ((unused)) signed int *const *__anonymous_object49[10], __attribute__ ((unused)) signed int *const *const *__anonymous_object50, __attribute__ ((unused)) signed int *const *const __anonymous_object51[10]){
    314278    __attribute__ ((unused)) signed int _X9_retval_fi_1;
    315279}
  • tests/functions.cfa

    r03606ce r06601401  
    1010// Created On       : Wed Aug 17 08:39:58 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Mar  5 11:02:25 2024
    13 // Update Count     : 34
     12// Last Modified On : Tue Nov  6 17:54:09 2018
     13// Update Count     : 13
    1414//
    1515
    1616// ANSI function definitions
    1717
    18 void h( void ) {}
     18void h(void) {}
    1919
    2020int f (
    21         int ( void ),
    22         int ( int ),
    23         int (( void )),
    24         int (( int )),
    25         void g( void )
    26 ) {
    27         (*g)();
     21        int (void),
     22        int (int),
     23        int ((void)),
     24        int ((int)),
     25        void g(void)
     26        ) {
     27        (* g)();
    2828        g();
    2929        g = h;
     
    3232int f1() {}
    3333int (f2()) {}
    34 int (*f3())() {}
     34int (* f3())() {}
    3535int * ((f4())) {}
    36 int ((*f5()))() {}
     36int ((* f5()))() {}
    3737int * f6() {}
    38 int * ( f7)() {}
     38int * (f7)() {}
    3939int ** f8() {}
    40 int * const * ( f9)() {}
     40int * const * (f9)() {}
    4141int (* f10())[] {}
    4242int (* f11())[][3] {}
     
    6666// Cforall extensions
    6767
    68 [] f();
    69 [void] f();
    70 [int] f();
    71 [] f( int );
    72 [void] f( int );
    73 [int] f( int );
    74 [] f() {}
    75 [void] fv() {}
    76 [int] f() {}
    77 [] f( int ) {}
    78 [void] fv( int ) {}
    79 [int] f( int ) {}
     68// [] f( );
     69[int] f( );
     70// [] f(int);
     71[int] f(int);
     72// [] f( ) {}
     73[int] f( ) {}
     74// [] f(int) {}
     75[int] f(int) {}
    8076
    81 [int x] f();
    82 [] f( int x );
    83 [void] fv( int x );
    84 //[int x] f( int x );
    85 //[int x] f() {}
    86 [] f2( int x ) {}
    87 [void] fv1( int x ) {}
    88 //[int x] f( int x ) {}
     77[int x] f( );
     78// [] f(int x);
     79//[int x] f(int x);
     80//[int x] f( ) {}
     81// [] f(int x) {}
     82//[int x] f(int x) {}
    8983
    90 [int, int x] f();
    91 [] f( int, int x );
    92 [void] fv( int, int x );
    93 [int, int x] f( int, int x );
    94 [int, int x] f() {}
    95 [] f( int, int x ) {}
    96 [void] fv( int, int x ) {}
    97 [int, int x] f( int, int x ) {}
     84[int, int x] f( );
     85// [] f(int, int x);
     86[int, int x] f(int, int x);
     87[int, int x] f( ) {}
     88// [] f(int, int x) {}
     89[int, int x] f(int, int x) {}
    9890
    99 [int, int x, int] f();
    100 [] f( int, int x, int );
    101 [void] fv( int, int x, int );
    102 [int, int x, int] f( int, int x, int );
    103 [int, int x, int] f() {}
    104 [] f( int, int x, int ) {}
    105 [void] fv( int, int x, int ) {}
    106 [int, int x, int] f( int, int x, int ) {}
     91[int, int x, int] f( );
     92// [] f(int, int x, int);
     93[int, int x, int] f(int, int x, int);
     94[int, int x, int] f( ) {}
     95// [] f(int, int x, int) {}
     96[int, int x, int] f(int, int x, int) {}
    10797
    108 [int, int x, * int y] f();
    109 [] f( int, int x, * int y );
    110 [void] fv( int, int x, * int y );
    111 [int, int x, * int y] f( int, int x, * int y );
    112 [int, int x, * int y] f() {}
    113 [] f( int, int x, * int y ) {}
    114 [void] fv( int, int x, * int y ) {}
    115 [int, int x, * int y] f( int, int x, * int y ) {}
     98[int, int x, * int y] f( );
     99// [] f(int, int x, * int y);
     100[int, int x, * int y] f(int, int x, * int y);
     101[int, int x, * int y] f( ) {}
     102// [] f(int, int x, * int y) {}
     103[int, int x, * int y] f(int, int x, * int y) {}
    116104
    117105// function prototypes
     
    128116        int ( int, int p ),
    129117        [int](int)
    130 ) {
    131         int (* (* pc )[][10])[][3];
     118        ) {
     119        int (* (* pc)[][10])[][3];
    132120        * [][10] * [][3] int p;
    133         * [] * [int]( int ) p;
     121        * [] * [int](int) p;
    134122}
    135123
     
    161149        int * const * const ([]),
    162150        int * const * const ([10])
    163 );
     151        );
    164152
    165153int f(
     
    182170        int * const * const ([]),
    183171        int * const * const ([10])
    184 ) {}
     172        ) {
     173}
    185174
    186175typedef int T;
    187176
    188 int f( T ( *f ), T t ) {
    189         T ( T );
     177int f( T (* f), T t ) {
     178        T (T);
    190179}
    191180
Note: See TracChangeset for help on using the changeset viewer.