Changeset d67cdb7


Ignore:
Timestamp:
Sep 26, 2017, 11:27:38 PM (7 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
5dc26f5
Parents:
201aeb9
Message:

merge

Files:
11 added
6 deleted
70 edited

Legend:

Unmodified
Added
Removed
  • doc/proposals/concurrency/Makefile

    r201aeb9 rd67cdb7  
    1717text/concurrency \
    1818text/parallelism \
     19text/together \
     20text/future \
    1921}
    2022
  • doc/proposals/concurrency/annex/glossary.tex

    r201aeb9 rd67cdb7  
    101101\newacronym{api}{API}{Application Program Interface}
    102102\newacronym{raii}{RAII}{Ressource Acquisition Is Initialization}
     103\newacronym{numa}{NUMA}{Non-Uniform Memory Access}
  • doc/proposals/concurrency/text/cforall.tex

    r201aeb9 rd67cdb7  
    1515int x, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    1616&r1 = x,    &&r2 = r1,   &&&r3 = r2;
    17 ***p3 = 3;                                      // change x
    18 r3 = 3;                                         // change x, ***r3
    19 **p3 = ...;                                     // change p1
    20 &r3 = ...;                                      // change r1, (&*)**r3
    21 *p3 = ...;                                      // change p2
    22 &&r3 = ...;                                     // change r2, (&(&*)*)*r3
    23 &&&r3 = p3;                                     // change r3 to p3, (&(&(&*)*)*)r3
    24 int y, z, & ar[3] = { x, y, z };                // initialize array of references
    25 &ar[1] = &z;                                    // change reference array element
    26 typeof( ar[1] ) p;                              // is int, i.e., the type of referenced object
    27 typeof( &ar[1] ) q;                             // is int &, i.e., the type of reference
    28 sizeof( ar[1] ) == sizeof( int );               // is true, i.e., the size of referenced object
    29 sizeof( &ar[1] ) == sizeof( int *);             // is true, i.e., the size of a reference
     17***p3 = 3;                              // change x
     18r3 = 3;                                 // change x, ***r3
     19**p3 = ...;                             // change p1
     20&r3 = ...;                              // change r1, (&*)**r3
     21*p3 = ...;                              // change p2
     22&&r3 = ...;                             // change r2, (&(&*)*)*r3
     23&&&r3 = p3;                             // change r3 to p3, (&(&(&*)*)*)r3
     24int y, z, & ar[3] = { x, y, z };        // initialize array of references
     25&ar[1] = &z;                            // change reference array element
     26typeof( ar[1] ) p;                      // is int, i.e., the type of referenced object
     27typeof( &ar[1] ) q;                     // is int &, i.e., the type of reference
     28sizeof( ar[1] ) == sizeof( int );       // is true, i.e., the size of referenced object
     29sizeof( &ar[1] ) == sizeof( int *);     // is true, i.e., the size of a reference
    3030\end{cfacode}
    3131The important thing to take away from this code snippet is that references offer a handle to an object much like pointers but which is automatically derefferenced when convinient.
     
    3636\begin{cfacode}
    3737// selection based on type and number of parameters
    38 void f( void );                                 // (1)
    39 void f( char );                                 // (2)
    40 void f( int, double );                          // (3)
    41 f();                                            // select (1)
    42 f( 'a' );                                       // select (2)
    43 f( 3, 5.2 );                                    // select (3)
     38void f( void );                         // (1)
     39void f( char );                         // (2)
     40void f( int, double );                  // (3)
     41f();                                    // select (1)
     42f( 'a' );                               // select (2)
     43f( 3, 5.2 );                            // select (3)
    4444
    4545// selection based on  type and number of returns
    46 char f( int );                                  // (1)
    47 double f( int );                                // (2)
    48 [ int, double ] f( int );                       // (3)
    49 char c = f( 3 );                                // select (1)
    50 double d = f( 4 );                              // select (2)
    51 [ int, double ] t = f( 5 );                     // select (3)
     46char f( int );                          // (1)
     47double f( int );                        // (2)
     48[ int, double ] f( int );               // (3)
     49char c = f( 3 );                        // select (1)
     50double d = f( 4 );                      // select (2)
     51[ int, double ] t = f( 5 );             // select (3)
    5252\end{cfacode}
    5353This feature is particularly important for concurrency since the runtime system relies on creating different types do represent concurrency objects. Therefore, overloading is necessary to prevent the need for long prefixes and other naming conventions that prevent clashes. As seen in chapter \ref{basics}, the main is an example of routine that benefits from overloading when concurrency in introduced.
     
    5656Overloading also extends to operators. The syntax for denoting operator-overloading is to name a routine with the symbol of the operator and question marks where the arguments of the operation would be, like so :
    5757\begin{cfacode}
    58 int ++?( int op );                              // unary prefix increment
    59 int ?++( int op );                              // unary postfix increment
    60 int ?+?( int op1, int op2 );                    // binary plus
    61 int ?<=?( int op1, int op2 );                   // binary less than
    62 int ?=?( int & op1, int op2 );                  // binary assignment
    63 int ?+=?( int & op1, int op2 );                 // binary plus-assignment
     58int ++?( int op );                      // unary prefix increment
     59int ?++( int op );                      // unary postfix increment
     60int ?+?( int op1, int op2 );            // binary plus
     61int ?<=?( int op1, int op2 );           // binary less than
     62int ?=?( int & op1, int op2 );          // binary assignment
     63int ?+=?( int & op1, int op2 );         // binary plus-assignment
    6464
    6565struct S { int i, j; };
    66 S ?+?( S op1, S op2 ) {                         // add two structures
     66S ?+?( S op1, S op2 ) {                 // add two structures
    6767        return (S){ op1.i + op2.i, op1.j + op2.j };
    6868}
    6969S s1 = { 1, 2 }, s2 = { 2, 3 }, s3;
    70 s3 = s1 + s2;                                   // compute sum: s3 == { 2, 5 }
     70s3 = s1 + s2;                           // compute sum: s3 == { 2, 5 }
    7171\end{cfacode}
    7272
     
    7474
    7575\section{Constructors/Destructors}
    76 \CFA uses the following syntax for constructors and destructors :
     76Object life time is often a challenge in concurrency. \CFA uses the approach of giving concurrent meaning to object life time as a mean of synchronization and/or mutual exclusion. Since \CFA relies heavily on the life time of objects, Constructors \& Destructors are a the core of the features required for concurrency and parallelism. \CFA uses the following syntax for constructors and destructors :
    7777\begin{cfacode}
    7878struct S {
     
    8080        int * ia;
    8181};
    82 void ?{}( S & s, int asize ) with s {           // constructor operator
    83         size = asize;                           // initialize fields
     82void ?{}( S & s, int asize ) with s {   // constructor operator
     83        size = asize;                   // initialize fields
    8484        ia = calloc( size, sizeof( S ) );
    8585}
    86 void ^?{}( S & s ) with s {                     // destructor operator
    87         free( ia );                             // de-initialization fields
     86void ^?{}( S & s ) with s {             // destructor operator
     87        free( ia );                     // de-initialization fields
    8888}
    8989int main() {
    90         S x = { 10 }, y = { 100 };              // implict calls: ?{}( x, 10 ), ?{}( y, 100 )
    91         ...                                     // use x and y
    92         ^x{};  ^y{};                            // explicit calls to de-initialize
    93         x{ 20 };  y{ 200 };                     // explicit calls to reinitialize
    94         ...                                     // reuse x and y
    95 }                                               // implict calls: ^?{}( y ), ^?{}( x )
     90        S x = { 10 }, y = { 100 };      // implict calls: ?{}( x, 10 ), ?{}( y, 100 )
     91        ...                             // use x and y
     92        ^x{};  ^y{};                    // explicit calls to de-initialize
     93        x{ 20 };  y{ 200 };             // explicit calls to reinitialize
     94        ...                             // reuse x and y
     95}                                       // implict calls: ^?{}( y ), ^?{}( x )
    9696\end{cfacode}
    9797The language guarantees that every object and all their fields are constructed. Like \CC construction is automatically done on declaration and destruction done when the declared variables reach the end of its scope.
  • doc/proposals/concurrency/text/concurrency.tex

    r201aeb9 rd67cdb7  
    6969int f5(graph(monitor*) & mutex m);
    7070\end{cfacode}
    71 The problem is to indentify which object(s) should be acquired. Furthermore, each object needs to be acquired only once. In the case of simple routines like \code{f1} and \code{f2} it is easy to identify an exhaustive list of objects to acquire on entry. Adding indirections (\code{f3}) still allows the compiler and programmer to indentify which object is acquired. However, adding in arrays (\code{f4}) makes it much harder. Array lengths are not necessarily known in C, and even then making sure objects are only acquired once becomes none-trivial. This can be extended to absurd limits like \code{f5}, which uses a graph of monitors. To keep everyone as sane as possible~\cite{Chicken}, this projects imposes the requirement that a routine may only acquire one monitor per parameter and it must be the type of the parameter with one level of indirection (ignoring potential qualifiers). Also note that while routine \code{f3} can be supported, meaning that monitor \code{**m} is be acquired, passing an array to this routine would be type safe and yet result in undefined behavior because only the first element of the array is acquired. This is specially true for non-copyable objects like monitors, where an array of pointers is simplest way to express a group of monitors. However, this ambiguity is part of the C type-system with respects to arrays. For this reason, \code{mutex} is disallowed in the context where arrays may be passed:
     71The problem is to indentify which object(s) should be acquired. Furthermore, each object needs to be acquired only once. In the case of simple routines like \code{f1} and \code{f2} it is easy to identify an exhaustive list of objects to acquire on entry. Adding indirections (\code{f3}) still allows the compiler and programmer to indentify which object is acquired. However, adding in arrays (\code{f4}) makes it much harder. Array lengths are not necessarily known in C, and even then making sure objects are only acquired once becomes none-trivial. This can be extended to absurd limits like \code{f5}, which uses a graph of monitors. To make the issue tractable, this projects imposes the requirement that a routine may only acquire one monitor per parameter and it must be the type of the parameter with one level of indirection (ignoring potential qualifiers). Also note that while routine \code{f3} can be supported, meaning that monitor \code{**m} is be acquired, passing an array to this routine would be type safe and yet result in undefined behavior because only the first element of the array is acquired. This is specially true for non-copyable objects like monitors, where an array of pointers is simplest way to express a group of monitors. However, this ambiguity is part of the C type-system with respects to arrays. For this reason, \code{mutex} is disallowed in the context where arrays may be passed:
    7272
    7373\begin{cfacode}
     
    608608% ======================================================================
    609609% ======================================================================
    610 There are several challenges specific to \CFA when implementing internal scheduling. These challenges are direct results of \gls{group-acquire} and loose object definitions. These two constraints are to root cause of most design decisions in the implementation of internal scheduling. Furthermore, to avoid the head-aches of dynamically allocating memory in a concurrent environment, the internal-scheduling design is entirely free of mallocs and other dynamic memory allocation scheme. This is to avoid the chicken and egg problem of having a memory allocator that relies on the threading system and a threading system that relies on the runtime. This extra goal, means that memory management is a constant concern in the design of the system.
     610There are several challenges specific to \CFA when implementing internal scheduling. These challenges are direct results of \gls{group-acquire} and loose object definitions. These two constraints are to root cause of most design decisions in the implementation of internal scheduling. Furthermore, to avoid the head-aches of dynamically allocating memory in a concurrent environment, the internal-scheduling design is entirely free of mallocs and other dynamic memory allocation scheme. This is to avoid the chicken and egg problem \cite{Chicken} of having a memory allocator that relies on the threading system and a threading system that relies on the runtime. This extra goal, means that memory management is a constant concern in the design of the system.
    611611
    612612The main memory concern for concurrency is queues. All blocking operations are made by parking threads onto queues. These queues need to be intrinsic\cit to avoid the need memory allocation. This entails that all the fields needed to keep track of all needed information. Since internal scheduling can use an unbound amount of memory (depending on \gls{group-acquire}) statically defining information information in the intrusive fields of threads is insufficient. The only variable sized container that does not require memory allocation is the callstack, which is heavily used in the implementation of internal scheduling. Particularly the GCC extension variable length arrays which is used extensively.
     
    832832To support multi-monitor external scheduling means that some kind of entry-queues must be used that is aware of both monitors. However, acceptable routines must be aware of the entry queues which means they must be stored inside at least one of the monitors that will be acquired. This in turn adds the requirement a systematic algorithm of disambiguating which queue is relavant regardless of user ordering. The proposed algorithm is to fall back on monitors lock ordering and specify that the monitor that is acquired first is the lock with the relevant entry queue. This assumes that the lock acquiring order is static for the lifetime of all concerned objects but that is a reasonable constraint. This algorithm choice has two consequences, the entry queue of the highest priority monitor is no longer a true FIFO queue and the queue of the lowest priority monitor is both required and probably unused. The queue can no longer be a FIFO queue because instead of simply containing the waiting threads in order arrival, they also contain the second mutex. Therefore, another thread with the same highest priority monitor but a different lowest priority monitor may arrive first but enter the critical section after a thread with the correct pairing. Secondly, since it may not be known at compile time which monitor will be the lowest priority monitor, every monitor needs to have the correct queues even though it is probable that half the multi-monitor queues will go unused for the entire duration of the program.
    833833
    834 % ======================================================================
    835 % ======================================================================
    836 \section{Other concurrency tools}
    837 % ======================================================================
    838 % ======================================================================
    839 % \TODO
     834
     835\subsection{Internals}
     836The complete mask can be pushed to any one, we are in a context where we already have full ownership of (at least) every concerned monitor and therefore monitors will refuse all calls no matter what.
  • doc/proposals/concurrency/text/intro.tex

    r201aeb9 rd67cdb7  
    33% ======================================================================
    44
    5 This proposal provides a minimal concurrency API that is simple, efficient and can be reused to build higher-level features. The simplest possible concurrency system is a thread and a lock but this low-level approach is hard to master. An easier approach for users is to support higher-level constructs as the basis of the concurrency, in \CFA. Indeed, for highly productive parallel programming, high-level approaches are much more popular~\cite{HPP:Study}. Examples are task based, message passing and implicit threading. Therefore a high-level approach is adapted in \CFA
     5This proposal provides a minimal concurrency API that is simple, efficient and can be reused to build higher-level features. The simplest possible concurrency system is a thread and a lock but this low-level approach is hard to master. An easier approach for users is to support higher-level constructs as the basis of the concurrency, in \CFA. Indeed, for highly productive concurrent programming, high-level approaches are much more popular~\cite{HPP:Study}. Examples are task based, message passing and implicit threading. Therefore a high-level approach is adopted in \CFA
    66
    7 There are actually two problems that need to be solved in the design of concurrency for a programming language: which concurrency and which parallelism tools are available to the users. While these two concepts are often combined, they are in fact distinct concepts that require different tools~\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.
     7There are actually two problems that need to be solved in the design of concurrency for a programming language: which concurrency and which parallelism tools are available to the programmers. While these two concepts are often combined, they are in fact distinct, requiring different tools~\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.
  • doc/proposals/concurrency/text/parallelism.tex

    r201aeb9 rd67cdb7  
    1111\section{Paradigm}
    1212\subsection{User-level threads}
    13 A direct improvement on the \gls{kthread} approach is to use \glspl{uthread}. These threads offer most of the same features that the operating system already provide but can be used on a much larger scale. This approach is the most powerfull solution as it allows all the features of multi-threading, while removing several of the more expensives costs of using kernel threads. The down side is that almost none of the low-level threading problems are hidden, users still have to think about data races, deadlocks and synchronization issues. These issues can be somewhat alleviated by a concurrency toolkit with strong garantees but the parallelism toolkit offers very little to reduce complexity in itself.
     13A direct improvement on the \gls{kthread} approach is to use \glspl{uthread}. These threads offer most of the same features that the operating system already provide but can be used on a much larger scale. This approach is the most powerfull solution as it allows all the features of multi-threading, while removing several of the more expensive costs of kernel threads. The down side is that almost none of the low-level threading problems are hidden; users still have to think about data races, deadlocks and synchronization issues. These issues can be somewhat alleviated by a concurrency toolkit with strong garantees but the parallelism toolkit offers very little to reduce complexity in itself.
    1414
    1515Examples of languages that support \glspl{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}.
    1616
    1717\subsection{Fibers : user-level threads without preemption}
    18 A popular varient of \glspl{uthread} is what is often reffered to as \glspl{fiber}. However, \glspl{fiber} do not present meaningful semantical differences with \glspl{uthread}. Advocates of \glspl{fiber} list their high performance and ease of implementation as majors strenghts of \glspl{fiber} but the performance difference between \glspl{uthread} and \glspl{fiber} is controversial and the ease of implementation, while true, is a weak argument in the context of language design. Therefore this proposal largely ignore fibers.
     18A popular varient of \glspl{uthread} is what is often refered to as \glspl{fiber}. However, \glspl{fiber} do not present meaningful semantical differences with \glspl{uthread}. Advocates of \glspl{fiber} list their high performance and ease of implementation as majors strenghts of \glspl{fiber} but the performance difference between \glspl{uthread} and \glspl{fiber} is controversial, and the ease of implementation, while true, is a weak argument in the context of language design. Therefore this proposal largely ignore fibers.
    1919
    2020An example of a language that uses fibers is Go~\cite{Go}
    2121
    2222\subsection{Jobs and thread pools}
    23 The approach on the opposite end of the spectrum is to base parallelism on \glspl{pool}. Indeed, \glspl{pool} offer limited flexibility but at the benefit of a simpler user interface. In \gls{pool} based systems, users express parallelism as units of work and a dependency graph (either explicit or implicit) that tie them together. This approach means users need not worry about concurrency but significantly limits the interaction that can occur among jobs. Indeed, any \gls{job} that blocks also blocks the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably. It can be argued that a solution to this problem is to use more workers than available cores. However, unless the number of jobs and the number of workers are comparable, having a significant amount of blocked jobs always results in idles cores.
     23The approach on the opposite end of the spectrum is to base parallelism on \glspl{pool}. Indeed, \glspl{pool} offer limited flexibility but at the benefit of a simpler user interface. In \gls{pool} based systems, users express parallelism as units of work, called jobs, and a dependency graph (either explicit or implicit) that tie them together. This approach means users need not worry about concurrency but significantly limits the interaction that can occur among jobs. Indeed, any \gls{job} that blocks also blocks the underlying worker, which effectively means the CPU utilization, and therefore throughput, suffers noticeably. It can be argued that a solution to this problem is to use more workers than available cores. However, unless the number of jobs and the number of workers are comparable, having a significant amount of blocked jobs always results in idles cores.
    2424
    2525The gold standard of this implementation is Intel's TBB library~\cite{TBB}.
    2626
    2727\subsection{Paradigm performance}
    28 While the choice between the three paradigms listed above may have significant performance implication, it is difficult to pindown the performance implications of chosing a model at the language level. Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload. Having a large amount of mostly independent units of work to execute almost guarantess that the \gls{pool} based system has the best performance thanks to the lower memory overhead. However, interactions between jobs can easily exacerbate contention. User-level threads allow fine-grain context switching, which results in better resource utilisation, but context switches will be more expansive and the extra control means users need to tweak more variables to get the desired performance. Furthermore, if the units of uninterrupted work are large enough the paradigm choice is largely amorticised by the actual work done.
     28While the choice between the three paradigms listed above may have significant performance implication, it is difficult to pindown the performance implications of chosing a model at the language level. Indeed, in many situations one of these paradigms may show better performance but it all strongly depends on the workload. Having a large amount of mostly independent units of work to execute almost guarantess that the \gls{pool} based system has the best performance thanks to the lower memory overhead (i.e., not thread stack per job). However, interactions among jobs can easily exacerbate contention. User-level threads allow fine-grain context switching, which results in better resource utilisation, but context switches is more expansive and the extra control means users need to tweak more variables to get the desired performance. Finally, if the units of uninterrupted work are large enough the paradigm choice is largely amortised by the actual work done.
    2929
    30 \newpage
    3130\TODO
    32 \subsection{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
     31
     32\section{The \protect\CFA\ Kernel : Processors, Clusters and Threads}\label{kernel}
    3333
    3434
     35\subsubsection{Future Work: Machine setup}\label{machine}
     36While this was not done in the context of this proposal, another important aspect of clusters is affinity. While many common desktop and laptop PCs have homogeneous CPUs, other devices often have more heteregenous setups. For example, system using \acrshort{numa} configurations may benefit from users being able to tie clusters and/or kernel threads to certains CPU cores. OS support for CPU affinity is now common \cit, which means it is both possible and desirable for \CFA to offer an abstraction mechanism for portable CPU affinity.
     37
    3538\subsection{Paradigms}\label{cfaparadigms}
    36 Given these building blocks we can then reproduce the all three of the popular paradigms. Indeed, we get \glspl{uthread} as the default paradigm in \CFA. However, disabling \glspl{preemption} on the \gls{cfacluster} means \glspl{cfathread} effectively become \glspl{fiber}. Since several \glspl{cfacluster} with different scheduling policy can coexist in the same application, this allows \glspl{fiber} and \glspl{uthread} to coexist in the runtime of an application.
    37 
    38 % \subsection{High-level options}\label{tasks}
    39 %
    40 % \subsubsection{Thread interface}
    41 % constructors destructors
    42 %       initializer lists
    43 % monitors
    44 %
    45 % \subsubsection{Futures}
    46 %
    47 % \subsubsection{Implicit threading}
    48 % Finally, simpler applications can benefit greatly from having implicit parallelism. That is, parallelism that does not rely on the user to write concurrency. This type of parallelism can be achieved both at the language level and at the system level.
    49 %
    50 % \begin{center}
    51 % \begin{tabular}[t]{|c|c|c|}
    52 % Sequential & System Parallel & Language Parallel \\
    53 % \begin{lstlisting}
    54 % void big_sum(int* a, int* b,
    55 %                int* out,
    56 %                size_t length)
    57 % {
    58 %       for(int i = 0; i < length; ++i ) {
    59 %               out[i] = a[i] + b[i];
    60 %       }
    61 % }
    62 %
    63 %
    64 %
    65 %
    66 %
    67 % int* a[10000];
    68 % int* b[10000];
    69 % int* c[10000];
    70 % //... fill in a and b ...
    71 % big_sum(a, b, c, 10000);
    72 % \end{lstlisting} &\begin{lstlisting}
    73 % void big_sum(int* a, int* b,
    74 %                int* out,
    75 %                size_t length)
    76 % {
    77 %       range ar(a, a + length);
    78 %       range br(b, b + length);
    79 %       range or(out, out + length);
    80 %       parfor( ai, bi, oi,
    81 %       [](int* ai, int* bi, int* oi) {
    82 %               oi = ai + bi;
    83 %       });
    84 % }
    85 %
    86 % int* a[10000];
    87 % int* b[10000];
    88 % int* c[10000];
    89 % //... fill in a and b ...
    90 % big_sum(a, b, c, 10000);
    91 % \end{lstlisting}&\begin{lstlisting}
    92 % void big_sum(int* a, int* b,
    93 %                int* out,
    94 %                size_t length)
    95 % {
    96 %       for (ai, bi, oi) in (a, b, out) {
    97 %               oi = ai + bi;
    98 %       }
    99 % }
    100 %
    101 %
    102 %
    103 %
    104 %
    105 % int* a[10000];
    106 % int* b[10000];
    107 % int* c[10000];
    108 % //... fill in a and b ...
    109 % big_sum(a, b, c, 10000);
    110 % \end{lstlisting}
    111 % \end{tabular}
    112 % \end{center}
    113 %
    114 % \subsection{Machine setup}\label{machine}
    115 % Threads are all good and well but wee still some OS support to fully utilize available hardware.
    116 %
    117 % \textbf{\large{Work in progress...}} Do wee need something beyond specifying the number of kernel threads?
     39Given these building blocks, it is possible to reproduce all three of the popular paradigms. Indeed, \glspl{uthread} is the default paradigm in \CFA. However, disabling \glspl{preemption} on the \gls{cfacluster} means \glspl{cfathread} effectively become \glspl{fiber}. Since several \glspl{cfacluster} with different scheduling policy can coexist in the same application, this allows \glspl{fiber} and \glspl{uthread} to coexist in the runtime of an application. Finally, it is possible to build executors for thread pools from \glspl{uthread} or \glspl{fiber}.
  • doc/proposals/concurrency/thesis.tex

    r201aeb9 rd67cdb7  
    11% requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended
    22
    3 % inline code ©...© (copyright symbol) emacs: C-q M-)
    4 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    5 % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    6 % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    7 % LaTex escape §...§ (section symbol) emacs: C-q M-'
    8 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     3% inline code �...� (copyright symbol) emacs: C-q M-)
     4% red highlighting �...� (registered trademark symbol) emacs: C-q M-.
     5% blue highlighting �...� (sharp s symbol) emacs: C-q M-_
     6% green highlighting �...� (cent symbol) emacs: C-q M-"
     7% LaTex escape �...� (section symbol) emacs: C-q M-'
     8% keyword escape �...� (pilcrow symbol) emacs: C-q M-^
    99% math escape $...$ (dollar symbol)
    1010
     
    2727\usepackage{multicol}
    2828\usepackage[acronym]{glossaries}
    29 \usepackage{varioref}   
     29\usepackage{varioref}
    3030\usepackage{listings}                                           % format program code
    3131\usepackage[flushmargin]{footmisc}                              % support label/reference in footnote
     
    103103\input{parallelism}
    104104
    105 \chapter{Putting it all together}
     105\input{together}
     106
     107\input{future}
    106108
    107109\chapter{Conclusion}
    108 
    109 \chapter{Future work}
    110 Concurrency and parallelism is still a very active field that strongly benefits from hardware advances. As such certain features that aren't necessarily mature enough in their current state could become relevant in the lifetime of \CFA.
    111 \subsection{Transactions}
    112110
    113111\section*{Acknowledgements}
  • doc/proposals/concurrency/version

    r201aeb9 rd67cdb7  
    1 0.9.180
     10.10.2
  • src/CodeGen/CodeGenerator.cc

    r201aeb9 rd67cdb7  
    443443        void CodeGenerator::postvisit( UntypedExpr * untypedExpr ) {
    444444                extension( untypedExpr );
    445                 if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
     445                if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->function ) ) {
    446446                        OperatorInfo opInfo;
    447                         if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
    448                                 std::list< Expression* >::iterator arg = untypedExpr->get_args().begin();
     447                        if ( operatorLookup( nameExpr->name, opInfo ) ) {
     448                                std::list< Expression* >::iterator arg = untypedExpr->args.begin();
    449449                                switch ( opInfo.type ) {
    450450                                  case OT_INDEX:
    451                                         assert( untypedExpr->get_args().size() == 2 );
     451                                        assert( untypedExpr->args.size() == 2 );
    452452                                        (*arg++)->accept( *visitor );
    453453                                        output << "[";
     
    461461                                  case OT_CTOR:
    462462                                  case OT_DTOR:
    463                                         if ( untypedExpr->get_args().size() == 1 ) {
     463                                        if ( untypedExpr->args.size() == 1 ) {
    464464                                                // the expression fed into a single parameter constructor or destructor may contain side
    465465                                                // effects, so must still output this expression
     
    480480                                                (*arg++)->accept( *visitor );
    481481                                                output << opInfo.symbol << "{ ";
    482                                                 genCommaList( arg, untypedExpr->get_args().end() );
     482                                                genCommaList( arg, untypedExpr->args.end() );
    483483                                                output << "}) /* " << opInfo.inputName << " */";
    484484                                        } // if
     
    488488                                  case OT_PREFIXASSIGN:
    489489                                  case OT_LABELADDRESS:
    490                                         assert( untypedExpr->get_args().size() == 1 );
     490                                        assert( untypedExpr->args.size() == 1 );
    491491                                        output << "(";
    492492                                        output << opInfo.symbol;
     
    497497                                  case OT_POSTFIX:
    498498                                  case OT_POSTFIXASSIGN:
    499                                         assert( untypedExpr->get_args().size() == 1 );
     499                                        assert( untypedExpr->args.size() == 1 );
    500500                                        (*arg)->accept( *visitor );
    501501                                        output << opInfo.symbol;
     
    504504                                  case OT_INFIX:
    505505                                  case OT_INFIXASSIGN:
    506                                         assert( untypedExpr->get_args().size() == 2 );
     506                                        assert( untypedExpr->args.size() == 2 );
    507507                                        output << "(";
    508508                                        (*arg++)->accept( *visitor );
     
    517517                                } // switch
    518518                        } else {
    519                                 if ( nameExpr->get_name() == "..." ) { // case V1 ... V2 or case V1~V2
    520                                         assert( untypedExpr->get_args().size() == 2 );
    521                                         (*untypedExpr->get_args().begin())->accept( *visitor );
    522                                         output << " ... ";
    523                                         (*--untypedExpr->get_args().end())->accept( *visitor );
    524                                 } else {                                                                // builtin routines
    525                                         nameExpr->accept( *visitor );
    526                                         output << "(";
    527                                         genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
    528                                         output << ")";
    529                                 } // if
     519                                // builtin routines
     520                                nameExpr->accept( *visitor );
     521                                output << "(";
     522                                genCommaList( untypedExpr->args.begin(), untypedExpr->args.end() );
     523                                output << ")";
    530524                        } // if
    531525                } else {
    532                         untypedExpr->get_function()->accept( *visitor );
     526                        untypedExpr->function->accept( *visitor );
    533527                        output << "(";
    534                         genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
     528                        genCommaList( untypedExpr->args.begin(), untypedExpr->args.end() );
    535529                        output << ")";
    536530                } // if
     
    538532
    539533        void CodeGenerator::postvisit( RangeExpr * rangeExpr ) {
    540                 rangeExpr->get_low()->accept( *visitor );
     534                rangeExpr->low->accept( *visitor );
    541535                output << " ... ";
    542                 rangeExpr->get_high()->accept( *visitor );
     536                rangeExpr->high->accept( *visitor );
    543537        }
    544538
     
    885879
    886880        void CodeGenerator::postvisit( CaseStmt * caseStmt ) {
     881                updateLocation( caseStmt );
     882                output << indent;
    887883                if ( caseStmt->isDefault()) {
    888884                        output << "default";
     
    10261022} // namespace CodeGen
    10271023
     1024std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node ) {
     1025        if ( node ) {
     1026                node->print( out );
     1027        } else {
     1028                out << "nullptr";
     1029        }
     1030        return out;
     1031}
     1032
    10281033// Local Variables: //
    10291034// tab-width: 4 //
  • src/Concurrency/Keywords.cc

    r201aeb9 rd67cdb7  
    528528                DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
    529529                auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
    530                 // if( type ) std::cerr << "FRED2" << std::endl;
    531530                if( type && type->get_baseStruct()->is_thread() ) {
    532531                        addStartStatement( decl, param );
  • src/Concurrency/Waitfor.cc

    r201aeb9 rd67cdb7  
    2727#include "InitTweak/InitTweak.h"   // for getPointerBase
    2828#include "Parser/LinkageSpec.h"    // for Cforall
    29 #include "SymTab/AddVisit.h"       // for acceptAndAdd
     29#include "ResolvExpr/Resolver.h"   // for findVoidExpression
    3030#include "SynTree/Constant.h"      // for Constant
    3131#include "SynTree/Declaration.h"   // for StructDecl, FunctionDecl, ObjectDecl
     
    112112        //=============================================================================================
    113113
    114         class GenerateWaitForPass final : public WithStmtsToAdd {
     114        class GenerateWaitForPass final : public WithIndexer {
    115115          public:
    116116
     
    126126
    127127                ObjectDecl * declare( unsigned long count, CompoundStmt * stmt );
     128                ObjectDecl * declareFlag( CompoundStmt * stmt );
     129                Statement  * makeSetter( ObjectDecl * flag );
    128130                ObjectDecl * declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt );
    129                 void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt );
    130                 Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, CompoundStmt * stmt );
    131                 Expression * call();
    132                 void choose();
     131                void         init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * settter, CompoundStmt * stmt );
     132                Expression * init_timeout( Expression *& time, Expression *& time_cond, bool has_else, Expression *& else_cond, Statement * settter, CompoundStmt * stmt );
     133                Expression * call(size_t count, ObjectDecl * acceptables, Expression * timeout, CompoundStmt * stmt);
     134                void         choose( WaitForStmt * waitfor, Expression  * result, CompoundStmt * stmt );
    133135
    134136                static void implement( std::list< Declaration * > & translationUnit ) {
     
    140142          private:
    141143                FunctionDecl        * decl_waitfor    = nullptr;
     144                StructDecl          * decl_mask       = nullptr;
    142145                StructDecl          * decl_acceptable = nullptr;
    143146                StructDecl          * decl_monitor    = nullptr;
    144                 DeclarationWithType * decl_m_func     = nullptr;
    145                 DeclarationWithType * decl_m_count    = nullptr;
    146                 DeclarationWithType * decl_m_monitors = nullptr;
    147                 DeclarationWithType * decl_m_isdtor   = nullptr;
    148147
    149148                static std::unique_ptr< Type > generic_func;
    150149
     150                UniqueName namer_acc = "__acceptables_"s;
     151                UniqueName namer_idx = "__index_"s;
     152                UniqueName namer_flg = "__do_run_"s;
     153                UniqueName namer_msk = "__mask_"s;
    151154                UniqueName namer_mon = "__monitors_"s;
    152                 UniqueName namer_acc = "__acceptables_"s;
    153155                UniqueName namer_tim = "__timeout_"s;
    154156        };
     
    167169        namespace {
    168170                Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) {
    169                         return new ApplicationExpr(
     171                        return new UntypedExpr(
    170172                                new NameExpr( "?[?]" ),
    171173                                {
     
    177179
    178180                Expression * makeOpAssign( Expression * lhs, Expression * rhs ) {
    179                         return new ApplicationExpr(
     181                        return new UntypedExpr(
    180182                                        new NameExpr( "?=?" ),
    181183                                        { lhs, rhs }
     
    183185                }
    184186
    185                 Expression * makeOpMember( Expression * sue, DeclarationWithType * mem ) {
    186                         return new MemberExpr( mem, sue );
    187                 }
    188 
    189                 Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, DeclarationWithType * member, Expression * value ) {
    190                         return new ExprStmt(
    191                                 noLabels,
    192                                 makeOpAssign(
    193                                         makeOpMember(
    194                                                 makeOpIndex(
    195                                                         object,
    196                                                         index
    197                                                 ),
    198                                                 member
     187                Expression * makeOpMember( Expression * sue, const std::string & mem ) {
     188                        return new UntypedMemberExpr( new NameExpr( mem ), sue );
     189                }
     190
     191                Statement * makeAccStatement( DeclarationWithType * object, unsigned long index, const std::string & member, Expression * value, const SymTab::Indexer & indexer ) {
     192                        std::unique_ptr< Expression > expr( makeOpAssign(
     193                                makeOpMember(
     194                                        makeOpIndex(
     195                                                object,
     196                                                index
    199197                                        ),
    200                                         value
    201                                 )
    202                         );
     198                                        member
     199                                ),
     200                                value
     201                        ) );
     202
     203                        return new ExprStmt( noLabels, ResolvExpr::findVoidExpression( expr.get(), indexer ) );
    203204                }
    204205
     
    208209                        return new ConstantExpr( Constant::from_bool( ifnull ) );
    209210                }
     211
     212                VariableExpr * extractVariable( Expression * func ) {
     213                        if( VariableExpr * var = dynamic_cast< VariableExpr * >( func ) ) {
     214                                return var;
     215                        }
     216
     217                        CastExpr * cast = strict_dynamic_cast< CastExpr * >( func );
     218                        return strict_dynamic_cast< VariableExpr * >( cast->arg );
     219                }
     220
     221                Expression * detectIsDtor( Expression * func ) {
     222                        VariableExpr * typed_func = extractVariable( func );
     223                        bool is_dtor = InitTweak::isDestructor( typed_func->var );
     224                        return new ConstantExpr( Constant::from_bool( is_dtor ) );
     225                }
    210226        };
    211227
     
    216232
    217233        void GenerateWaitForPass::premutate( FunctionDecl * decl) {
    218                 if( decl->name != "__accept_internal" ) return;
     234                if( decl->name != "__waitfor_internal" ) return;
    219235
    220236                decl_waitfor = decl;
     
    227243                        assert( !decl_acceptable );
    228244                        decl_acceptable = decl;
    229                         for( Declaration * field : decl_acceptable->members ) {
    230                                      if( field->name == "func"    ) decl_m_func     = strict_dynamic_cast< DeclarationWithType * >( field );
    231                                 else if( field->name == "count"   ) decl_m_count    = strict_dynamic_cast< DeclarationWithType * >( field );
    232                                 else if( field->name == "monitor" ) decl_m_monitors = strict_dynamic_cast< DeclarationWithType * >( field );
    233                                 else if( field->name == "is_dtor" ) decl_m_isdtor   = strict_dynamic_cast< DeclarationWithType * >( field );
    234                         }
    235 
     245                }
     246                else if( decl->name == "__waitfor_mask_t" ) {
     247                        assert( !decl_mask );
     248                        decl_mask = decl;
    236249                }
    237250                else if( decl->name == "monitor_desc" ) {
     
    242255
    243256        Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
    244                 return waitfor;
    245 
    246                 if( !decl_monitor || !decl_acceptable ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
     257                if( !decl_monitor || !decl_acceptable || !decl_mask ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
    247258
    248259                CompoundStmt * stmt = new CompoundStmt( noLabels );
    249260
    250261                ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
     262                ObjectDecl * flag        = declareFlag( stmt );
     263                Statement  * setter      = makeSetter( flag );
    251264
    252265                int index = 0;
    253266                for( auto & clause : waitfor->clauses ) {
    254                         init( acceptables, index, clause, stmt );
     267                        init( acceptables, index, clause, setter, stmt );
    255268
    256269                        index++;
     
    262275                        waitfor->orelse .statement,
    263276                        waitfor->orelse .condition,
     277                        setter,
    264278                        stmt
    265279                );
    266280
    267                 // Expression * result  = call( acceptables, timeout, orelse, stmt );
    268 
    269                 // choose( waitfor, result );
     281                CompoundStmt * compound = new CompoundStmt( noLabels );
     282                stmt->push_back( new IfStmt(
     283                        noLabels,
     284                        safeCond( new VariableExpr( flag ) ),
     285                        compound,
     286                        nullptr
     287                ));
     288
     289                Expression * result = call( waitfor->clauses.size(), acceptables, timeout, compound );
     290
     291                choose( waitfor, result, compound );
    270292
    271293                return stmt;
     
    274296        ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt )
    275297        {
    276                 ObjectDecl * acceptables = new ObjectDecl(
     298                ObjectDecl * acceptables = ObjectDecl::newObject(
    277299                        namer_acc.newName(),
    278                         noStorage,
    279                         LinkageSpec::Cforall,
    280                         nullptr,
    281300                        new ArrayType(
    282301                                noQualifiers,
     
    294313                stmt->push_back( new DeclStmt( noLabels, acceptables) );
    295314
     315                UntypedExpr * set = new UntypedExpr(
     316                        new NameExpr( "__builtin_memset" ),
     317                        {
     318                                new VariableExpr( acceptables ),
     319                                new ConstantExpr( Constant::from_int( 0 ) ),
     320                                new SizeofExpr( new VariableExpr( acceptables ) )
     321                        }
     322                );
     323
     324                Expression * resolved_set = ResolvExpr::findVoidExpression( set, indexer );
     325                delete set;
     326
     327                stmt->push_back( new ExprStmt( noLabels, resolved_set ) );
     328
    296329                return acceptables;
    297330        }
    298331
     332        ObjectDecl * GenerateWaitForPass::declareFlag( CompoundStmt * stmt ) {
     333                ObjectDecl * flag = ObjectDecl::newObject(
     334                        namer_flg.newName(),
     335                        new BasicType(
     336                                noQualifiers,
     337                                BasicType::Bool
     338                        ),
     339                        new SingleInit( new ConstantExpr( Constant::from_ulong( 0 ) ) )
     340                );
     341
     342                stmt->push_back( new DeclStmt( noLabels, flag) );
     343
     344                return flag;
     345        }
     346
     347        Statement * GenerateWaitForPass::makeSetter( ObjectDecl * flag ) {
     348                Expression * untyped = new UntypedExpr(
     349                        new NameExpr( "?=?" ),
     350                        {
     351                                new VariableExpr( flag ),
     352                                new ConstantExpr( Constant::from_ulong( 1 ) )
     353                        }
     354                );
     355
     356                Expression * expr = ResolvExpr::findVoidExpression( untyped, indexer );
     357                delete untyped;
     358
     359                return new ExprStmt( noLabels, expr );
     360        }
     361
    299362        ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
    300363
    301                 ObjectDecl * mon = new ObjectDecl(
     364                ObjectDecl * mon = ObjectDecl::newObject(
    302365                        namer_mon.newName(),
    303                         noStorage,
    304                         LinkageSpec::Cforall,
    305                         nullptr,
    306366                        new ArrayType(
    307367                                noQualifiers,
    308                                 new StructInstType(
     368                                new PointerType(
    309369                                        noQualifiers,
    310                                         decl_monitor
     370                                        new StructInstType(
     371                                                noQualifiers,
     372                                                decl_monitor
     373                                        )
    311374                                ),
    312375                                new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ),
     
    316379                        new ListInit(
    317380                                map_range < std::list<Initializer*> > ( clause.target.arguments, [this](Expression * expr ){
    318                                         return new SingleInit( expr );
     381                                        Expression * untyped = new CastExpr(
     382                                                new UntypedExpr(
     383                                                        new NameExpr( "get_monitor" ),
     384                                                        { expr }
     385                                                ),
     386                                                new PointerType(
     387                                                        noQualifiers,
     388                                                        new StructInstType(
     389                                                                noQualifiers,
     390                                                                decl_monitor
     391                                                        )
     392                                                )
     393                                        );
     394
     395                                        Expression * init = ResolvExpr::findSingleExpression( untyped, indexer );
     396                                        delete untyped;
     397                                        return new SingleInit( init );
    319398                                })
    320399                        )
     
    326405        }
    327406
    328         void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, CompoundStmt * stmt ) {
     407        void GenerateWaitForPass::init( ObjectDecl * acceptables, int index, WaitForStmt::Clause & clause, Statement * setter, CompoundStmt * stmt ) {
    329408
    330409                ObjectDecl * monitors = declMon( clause, stmt );
    331410
    332                 CompoundStmt * compound = new CompoundStmt( noLabels );
    333                 compound->push_back( makeAccStatement( acceptables, index, decl_m_func    , clause.target.function ) );
    334                 compound->push_back( makeAccStatement( acceptables, index, decl_m_count   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ) ) );
    335                 compound->push_back( makeAccStatement( acceptables, index, decl_m_monitors, new VariableExpr( monitors ) ) );
    336                 compound->push_back( makeAccStatement( acceptables, index, decl_m_isdtor  , new ConstantExpr( Constant::from_bool( true ) ) ) );
     411                Type * fptr_t = new PointerType( noQualifiers, new FunctionType( noQualifiers, true ) );
    337412
    338413                stmt->push_back( new IfStmt(
    339414                        noLabels,
    340415                        safeCond( clause.condition ),
    341                         compound,
     416                        new CompoundStmt({
     417                                makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
     418                                makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
     419                                makeAccStatement( acceptables, index, "list"   , new VariableExpr( monitors )                                              , indexer ),
     420                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
     421                                setter->clone()
     422                        }),
    342423                        nullptr
    343424                ));
     
    353434                bool has_else,
    354435                Expression *& else_cond,
     436                Statement * setter,
    355437                CompoundStmt * stmt
    356438        ) {
    357                 ObjectDecl * timeout = new ObjectDecl(
     439                ObjectDecl * timeout = ObjectDecl::newObject(
    358440                        namer_tim.newName(),
    359                         noStorage,
    360                         LinkageSpec::Cforall,
    361                         nullptr,
    362441                        new BasicType(
    363442                                noQualifiers,
     
    374453                        stmt->push_back( new IfStmt(
    375454                                noLabels,
    376                                 safeCond( else_cond ),
    377                                 new ExprStmt(
    378                                         noLabels,
    379                                         makeOpAssign(
    380                                                 new VariableExpr( timeout ),
    381                                                 time
    382                                         )
    383                                 ),
     455                                safeCond( time_cond ),
     456                                new CompoundStmt({
     457                                        new ExprStmt(
     458                                                noLabels,
     459                                                makeOpAssign(
     460                                                        new VariableExpr( timeout ),
     461                                                        time
     462                                                )
     463                                        ),
     464                                        setter->clone()
     465                                }),
    384466                                nullptr
    385467                        ));
     
    392474                                noLabels,
    393475                                safeCond( else_cond ),
    394                                 new ExprStmt(
    395                                         noLabels,
    396                                         makeOpAssign(
    397                                                 new VariableExpr( timeout ),
    398                                                 new ConstantExpr( Constant::from_ulong( 0 ) )
    399                                         )
    400                                 ),
     476                                new CompoundStmt({
     477                                        new ExprStmt(
     478                                                noLabels,
     479                                                makeOpAssign(
     480                                                        new VariableExpr( timeout ),
     481                                                        new ConstantExpr( Constant::from_ulong( 0 ) )
     482                                                )
     483                                        ),
     484                                        setter->clone()
     485                                }),
    401486                                nullptr
    402487                        ));
     
    405490                }
    406491
     492                delete setter;
     493
    407494                return new VariableExpr( timeout );
     495        }
     496
     497        Expression * GenerateWaitForPass::call(
     498                size_t count,
     499                ObjectDecl * acceptables,
     500                Expression * timeout,
     501                CompoundStmt * stmt
     502        ) {
     503                ObjectDecl * index = ObjectDecl::newObject(
     504                        namer_idx.newName(),
     505                        new BasicType(
     506                                noQualifiers,
     507                                BasicType::ShortSignedInt
     508                        ),
     509                        new SingleInit(
     510                                new ConstantExpr( Constant::from_int( -1 ) )
     511                        )
     512                );
     513
     514                stmt->push_back( new DeclStmt( noLabels, index ) );
     515
     516                ObjectDecl * mask = ObjectDecl::newObject(
     517                        namer_msk.newName(),
     518                        new StructInstType(
     519                                noQualifiers,
     520                                decl_mask
     521                        ),
     522                        new ListInit({
     523                                new SingleInit( new AddressExpr( new VariableExpr( index ) ) ),
     524                                new SingleInit( new VariableExpr( acceptables ) ),
     525                                new SingleInit( new ConstantExpr( Constant::from_ulong( count ) ) )
     526                        })
     527                );
     528
     529                stmt->push_back( new DeclStmt( noLabels, mask ) );
     530
     531                stmt->push_back( new ExprStmt(
     532                        noLabels,
     533                        new ApplicationExpr(
     534                                VariableExpr::functionPointer( decl_waitfor ),
     535                                {
     536                                        new CastExpr(
     537                                                new VariableExpr( mask ),
     538                                                new ReferenceType(
     539                                                        noQualifiers,
     540                                                        new StructInstType(
     541                                                                noQualifiers,
     542                                                                decl_mask
     543                                                        )
     544                                                )
     545                                        ),
     546                                        timeout
     547                                }
     548                        )
     549                ));
     550
     551                return new VariableExpr( index );
     552        }
     553
     554        void GenerateWaitForPass::choose(
     555                WaitForStmt * waitfor,
     556                Expression  * result,
     557                CompoundStmt * stmt
     558        ) {
     559                SwitchStmt * swtch = new SwitchStmt(
     560                        noLabels,
     561                        result,
     562                        std::list<Statement *>()
     563                );
     564
     565                unsigned long i = 0;
     566                for( auto & clause : waitfor->clauses ) {
     567                        swtch->statements.push_back(
     568                                new CaseStmt(
     569                                        noLabels,
     570                                        new ConstantExpr( Constant::from_ulong( i++ ) ),
     571                                        {
     572                                                clause.statement,
     573                                                new BranchStmt(
     574                                                        noLabels,
     575                                                        "",
     576                                                        BranchStmt::Break
     577                                                )
     578                                        }
     579                                )
     580                        );
     581                }
     582
     583                if(waitfor->timeout.statement) {
     584                        swtch->statements.push_back(
     585                                new CaseStmt(
     586                                        noLabels,
     587                                        new ConstantExpr( Constant::from_int( -2 ) ),
     588                                        {
     589                                                waitfor->timeout.statement,
     590                                                new BranchStmt(
     591                                                        noLabels,
     592                                                        "",
     593                                                        BranchStmt::Break
     594                                                )
     595                                        }
     596                                )
     597                        );
     598                }
     599
     600                if(waitfor->orelse.statement) {
     601                        swtch->statements.push_back(
     602                                new CaseStmt(
     603                                        noLabels,
     604                                        new ConstantExpr( Constant::from_int( -1 ) ),
     605                                        {
     606                                                waitfor->orelse.statement,
     607                                                new BranchStmt(
     608                                                        noLabels,
     609                                                        "",
     610                                                        BranchStmt::Break
     611                                                )
     612                                        }
     613                                )
     614                        );
     615                }
     616
     617                stmt->push_back( swtch );
    408618        }
    409619};
  • src/GenPoly/Box.cc

    r201aeb9 rd67cdb7  
    3232#include "Common/UniqueName.h"           // for UniqueName
    3333#include "Common/utility.h"              // for toString
    34 #include "DeclMutator.h"                 // for DeclMutator
    3534#include "FindFunction.h"                // for findFunction, findAndReplace...
    3635#include "GenPoly/ErasableScopedMap.h"   // for ErasableScopedMap<>::const_i...
     
    3938#include "Lvalue.h"                      // for generalizedLvalue
    4039#include "Parser/LinkageSpec.h"          // for C, Spec, Cforall, Intrinsic
    41 #include "PolyMutator.h"                 // for PolyMutator
    4240#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass
    4341#include "ResolvExpr/typeops.h"          // for typesCompatible
     
    6260                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
    6361
     62                class BoxPass {
     63                protected:
     64                        BoxPass() : scopeTyVars( TypeDecl::Data{} ) {}
     65                        TyVarMap scopeTyVars;
     66                };
     67
    6468                /// Adds layout-generation functions to polymorphic types
    65                 class LayoutFunctionBuilder final : public DeclMutator {
    66                         unsigned int functionNesting;  // current level of nested functions
     69                class LayoutFunctionBuilder final : public WithDeclsToAdd, public WithVisitorRef<LayoutFunctionBuilder>, public WithShortCircuiting {
     70                        unsigned int functionNesting = 0;  // current level of nested functions
    6771                public:
    68                         LayoutFunctionBuilder() : functionNesting( 0 ) {}
    69 
    70                         using DeclMutator::mutate;
    71                         virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
    72                         virtual Declaration *mutate( StructDecl *structDecl ) override;
    73                         virtual Declaration *mutate( UnionDecl *unionDecl ) override;
     72                        void previsit( FunctionDecl *functionDecl );
     73                        void previsit( StructDecl *structDecl );
     74                        void previsit( UnionDecl *unionDecl );
    7475                };
    7576
    7677                /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
    77                 class Pass1 final : public PolyMutator {
     78                class Pass1 final : public BoxPass, public WithTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
    7879                  public:
    7980                        Pass1();
    8081
    81                         using PolyMutator::mutate;
    82                         virtual Expression *mutate( ApplicationExpr *appExpr ) override;
    83                         virtual Expression *mutate( AddressExpr *addrExpr ) override;
    84                         virtual Expression *mutate( UntypedExpr *expr ) override;
    85                         virtual DeclarationWithType* mutate( FunctionDecl *functionDecl ) override;
    86                         virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
    87                         virtual Expression *mutate( CommaExpr *commaExpr ) override;
    88                         virtual Expression *mutate( ConditionalExpr *condExpr ) override;
    89                         virtual Statement * mutate( ReturnStmt *returnStmt ) override;
    90                         virtual Type *mutate( PointerType *pointerType ) override;
    91                         virtual Type * mutate( FunctionType *functionType ) override;
    92 
    93                         virtual void doBeginScope() override;
    94                         virtual void doEndScope() override;
     82                        void premutate( FunctionDecl * functionDecl );
     83                        void premutate( TypeDecl * typeDecl );
     84                        void premutate( CommaExpr * commaExpr );
     85                        Expression * postmutate( ApplicationExpr * appExpr );
     86                        Expression * postmutate( UntypedExpr *expr );
     87                        void premutate( AddressExpr * addrExpr );
     88                        Expression * postmutate( AddressExpr * addrExpr );
     89                        void premutate( ReturnStmt * returnStmt );
     90                        void premutate( PointerType * pointerType );
     91                        void premutate( FunctionType * functionType );
     92
     93                        void beginScope();
     94                        void endScope();
    9595                  private:
    9696                        /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
     
    129129                /// * Moves polymorphic returns in function types to pointer-type parameters
    130130                /// * adds type size and assertion parameters to parameter lists
    131                 class Pass2 final : public PolyMutator {
    132                   public:
    133                         template< typename DeclClass >
    134                         DeclClass *handleDecl( DeclClass *decl );
    135                         template< typename AggDecl >
    136                         AggDecl * handleAggDecl( AggDecl * aggDecl );
    137 
    138                         typedef PolyMutator Parent;
    139                         using Parent::mutate;
    140                         virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
    141                         virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
    142                         virtual StructDecl *mutate( StructDecl *structDecl ) override;
    143                         virtual UnionDecl *mutate( UnionDecl *unionDecl ) override;
    144                         virtual TraitDecl *mutate( TraitDecl *unionDecl ) override;
    145                         virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
    146                         virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ) override;
    147                         virtual Type *mutate( PointerType *pointerType ) override;
    148                         virtual Type *mutate( FunctionType *funcType ) override;
     131                struct Pass2 final : public BoxPass, public WithGuards {
     132                        void handleAggDecl();
     133
     134                        DeclarationWithType * postmutate( FunctionDecl *functionDecl );
     135                        void premutate( StructDecl *structDecl );
     136                        void premutate( UnionDecl *unionDecl );
     137                        void premutate( TraitDecl *unionDecl );
     138                        void premutate( TypeDecl *typeDecl );
     139                        void premutate( PointerType *pointerType );
     140                        void premutate( FunctionType *funcType );
    149141
    150142                  private:
     
    158150                /// * Calculates polymorphic offsetof expressions from offset array
    159151                /// * Inserts dynamic calculation of polymorphic type layouts where needed
    160                 class PolyGenericCalculator final : public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithTypeSubstitution {
     152                class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithTypeSubstitution {
    161153                public:
    162154                        PolyGenericCalculator();
     
    197189                        ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
    198190                        UniqueName bufNamer;                           ///< Namer for VLA buffers
    199                         TyVarMap scopeTyVars;
    200191                };
    201192
    202193                /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, sizeof expressions of polymorphic types with the proper variable, and strips fields from generic struct declarations.
    203                 class Pass3 final : public PolyMutator {
    204                   public:
     194                struct Pass3 final : public BoxPass, public WithGuards {
    205195                        template< typename DeclClass >
    206                         DeclClass *handleDecl( DeclClass *decl, Type *type );
    207 
    208                         using PolyMutator::mutate;
    209                         virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
    210                         virtual Declaration *mutate( StructDecl *structDecl ) override;
    211                         virtual Declaration *mutate( UnionDecl *unionDecl ) override;
    212                         virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
    213                         virtual TypedefDecl *mutate( TypedefDecl *objectDecl ) override;
    214                         virtual TypeDecl *mutate( TypeDecl *objectDecl ) override;
    215                         virtual Type *mutate( PointerType *pointerType ) override;
    216                         virtual Type *mutate( FunctionType *funcType ) override;
    217                   private:
     196                        void handleDecl( DeclClass * decl, Type * type );
     197
     198                        void premutate( ObjectDecl * objectDecl );
     199                        void premutate( FunctionDecl * functionDecl );
     200                        void premutate( TypedefDecl * typedefDecl );
     201                        void premutate( StructDecl * structDecl );
     202                        void premutate( UnionDecl * unionDecl );
     203                        void premutate( TypeDecl * typeDecl );
     204                        void premutate( PointerType * pointerType );
     205                        void premutate( FunctionType * funcType );
    218206                };
    219207        } // anonymous namespace
     
    247235
    248236        void box( std::list< Declaration *>& translationUnit ) {
    249                 LayoutFunctionBuilder layoutBuilder;
    250                 Pass1 pass1;
    251                 Pass2 pass2;
     237                PassVisitor<LayoutFunctionBuilder> layoutBuilder;
     238                PassVisitor<Pass1> pass1;
     239                PassVisitor<Pass2> pass2;
    252240                PassVisitor<PolyGenericCalculator> polyCalculator;
    253                 Pass3 pass3;
    254 
    255                 layoutBuilder.mutateDeclarationList( translationUnit );
    256                 mutateTranslationUnit/*All*/( translationUnit, pass1 );
    257                 mutateTranslationUnit/*All*/( translationUnit, pass2 );
     241                PassVisitor<Pass3> pass3;
     242
     243                acceptAll( translationUnit, layoutBuilder );
     244                mutateAll( translationUnit, pass1 );
     245                mutateAll( translationUnit, pass2 );
    258246                mutateAll( translationUnit, polyCalculator );
    259                 mutateTranslationUnit/*All*/( translationUnit, pass3 );
     247                mutateAll( translationUnit, pass3 );
    260248        }
    261249
    262250        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
    263251
    264         DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
    265                 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
     252        void LayoutFunctionBuilder::previsit( FunctionDecl *functionDecl ) {
     253                visit_children = false;
     254                maybeAccept( functionDecl->get_functionType(), *visitor );
    266255                ++functionNesting;
    267                 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     256                maybeAccept( functionDecl->get_statements(), *visitor );
    268257                --functionNesting;
    269                 return functionDecl;
    270258        }
    271259
     
    356344        }
    357345
    358         Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
     346        void LayoutFunctionBuilder::previsit( StructDecl *structDecl ) {
    359347                // do not generate layout function for "empty" tag structs
    360                 if ( structDecl->get_members().empty() ) return structDecl;
     348                visit_children = false;
     349                if ( structDecl->get_members().empty() ) return;
    361350
    362351                // get parameters that can change layout, exiting early if none
    363352                std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
    364                 if ( otypeParams.empty() ) return structDecl;
     353                if ( otypeParams.empty() ) return;
    365354
    366355                // build layout function signature
     
    413402                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
    414403
    415                 addDeclarationAfter( layoutDecl );
    416                 return structDecl;
     404                declsToAddAfter.push_back( layoutDecl );
    417405        }
    418406
    419         Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
     407        void LayoutFunctionBuilder::previsit( UnionDecl *unionDecl ) {
    420408                // do not generate layout function for "empty" tag unions
    421                 if ( unionDecl->get_members().empty() ) return unionDecl;
     409                visit_children = false;
     410                if ( unionDecl->get_members().empty() ) return;
    422411
    423412                // get parameters that can change layout, exiting early if none
    424413                std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
    425                 if ( otypeParams.empty() ) return unionDecl;
     414                if ( otypeParams.empty() ) return;
    426415
    427416                // build layout function signature
     
    456445                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
    457446
    458                 addDeclarationAfter( layoutDecl );
    459                 return unionDecl;
     447                declsToAddAfter.push_back( layoutDecl );
    460448        }
    461449
     
    501489                Pass1::Pass1() : tempNamer( "_temp" ) {}
    502490
    503                 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
     491                void Pass1::premutate( FunctionDecl *functionDecl ) {
    504492                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    505493                                // std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
    506                                 doBeginScope();
    507                                 scopeTyVars.beginScope();
    508 
    509                                 DeclarationWithType *oldRetval = retval;
     494                                GuardScope( scopeTyVars );
     495                                GuardValue( retval );
    510496
    511497                                // process polymorphic return value
    512498                                retval = nullptr;
    513                                 if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() != LinkageSpec::C ) {
    514                                         retval = functionDecl->get_functionType()->get_returnVals().front();
     499                                FunctionType *functionType = functionDecl->type;
     500                                if ( isDynRet( functionType ) && functionDecl->linkage != LinkageSpec::C ) {
     501                                        retval = functionType->returnVals.front();
    515502
    516503                                        // give names to unnamed return values
    517                                         if ( retval->get_name() == "" ) {
    518                                                 retval->set_name( "_retparm" );
    519                                                 retval->set_linkage( LinkageSpec::C );
     504                                        if ( retval->name == "" ) {
     505                                                retval->name = "_retparm";
     506                                                retval->linkage = LinkageSpec::C;
    520507                                        } // if
    521508                                } // if
    522509
    523                                 FunctionType *functionType = functionDecl->get_functionType();
    524                                 makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
    525 
    526                                 std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
     510                                makeTyVarMap( functionType, scopeTyVars );
     511
     512                                std::list< DeclarationWithType *> &paramList = functionType->parameters;
    527513                                std::list< FunctionType *> functions;
    528                                 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
    529                                         for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
     514                                for ( Type::ForallList::iterator tyVar = functionType->forall.begin(); tyVar != functionType->forall.end(); ++tyVar ) {
     515                                        for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) {
    530516                                                findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
    531517                                        } // for
     
    542528                                        } // if
    543529                                } // for
    544 
    545                                 functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
    546 
    547                                 scopeTyVars.endScope();
    548                                 retval = oldRetval;
    549                                 doEndScope();
    550530                                // std::cerr << "end function: " << functionDecl->get_mangleName() << std::endl;
    551531                        } // if
    552                         return functionDecl;
    553                 }
    554 
    555                 TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
     532                }
     533
     534                void Pass1::premutate( TypeDecl *typeDecl ) {
    556535                        addToTyVarMap( typeDecl, scopeTyVars );
    557                         return dynamic_cast<TypeDecl*>( Mutator::mutate( typeDecl ) );
    558                 }
    559 
    560                 Expression *Pass1::mutate( CommaExpr *commaExpr ) {
     536                }
     537
     538                void Pass1::premutate( CommaExpr *commaExpr ) {
    561539                        // Attempting to find application expressions that were mutated by the copy constructor passes
    562540                        // to use an explicit return variable, so that the variable can be reused as a parameter to the
     
    574552                                }
    575553                        }
    576 
    577                         commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
    578                         commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
    579                         return commaExpr;
    580                 }
    581 
    582                 Expression *Pass1::mutate( ConditionalExpr *condExpr ) {
    583                         condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) );
    584                         condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) );
    585                         condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) );
    586                         return condExpr;
    587 
    588554                }
    589555
     
    659625                ObjectDecl *Pass1::makeTemporary( Type *type ) {
    660626                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
    661                         stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     627                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
    662628                        return newObj;
    663629                }
     
    775741                                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
    776742                                        newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    777                                         stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
     743                                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
    778744                                        UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
    779745                                        assign->get_args().push_back( new VariableExpr( newObj ) );
    780746                                        assign->get_args().push_back( arg );
    781                                         stmtsToAdd.push_back( new ExprStmt( noLabels, assign ) );
     747                                        stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) );
    782748                                        arg = new AddressExpr( new VariableExpr( newObj ) );
    783749                                } // if
     
    961927                                                std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
    962928                                                adapter = answer.first;
    963                                                 stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
     929                                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, newAdapter ) );
    964930                                        } // if
    965931                                        assert( adapter != adapters.end() );
     
    11181084                }
    11191085
    1120                 Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
     1086                Expression *Pass1::postmutate( ApplicationExpr *appExpr ) {
    11211087                        // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
    11221088                        // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
     
    11241090                        // }
    11251091                        // std::cerr << "\n";
    1126                         appExpr->get_function()->acceptMutator( *this );
    1127                         mutateAll( appExpr->get_args(), *this );
    1128 
    1129                         assert( appExpr->get_function()->has_result() );
    1130                         FunctionType * function = getFunctionType( appExpr->get_function()->get_result() );
    1131                         assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->get_function()->get_result() ).c_str() );
     1092
     1093                        assert( appExpr->function->result );
     1094                        FunctionType * function = getFunctionType( appExpr->function->result );
     1095                        assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
    11321096
    11331097                        if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
     
    11821146                }
    11831147
    1184                 Expression *Pass1::mutate( UntypedExpr *expr ) {
    1185                         if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
    1186                                 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
     1148                Expression * Pass1::postmutate( UntypedExpr *expr ) {
     1149                        if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
     1150                                if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
    11871151                                        if ( name->get_name() == "*?" ) {
    1188                                                 Expression *ret = expr->get_args().front();
    1189                                                 expr->get_args().clear();
     1152                                                Expression *ret = expr->args.front();
     1153                                                expr->args.clear();
    11901154                                                delete expr;
    1191                                                 return ret->acceptMutator( *this );
     1155                                                return ret;
    11921156                                        } // if
    11931157                                } // if
    11941158                        } // if
    1195                         return PolyMutator::mutate( expr );
    1196                 }
    1197 
    1198                 Expression *Pass1::mutate( AddressExpr *addrExpr ) {
     1159                        return expr;
     1160                }
     1161
     1162                void Pass1::premutate( AddressExpr * ) { visit_children = false; }
     1163                Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
    11991164                        assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() );
    12001165
     
    12161181                        // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
    12171182                        // out of the if condition.
    1218                         addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
     1183                        addrExpr->arg = addrExpr->get_arg()->acceptMutator( *visitor );
    12191184                        // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
    12201185                        bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
     
    12311196                }
    12321197
    1233                 Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
    1234                         if ( retval && returnStmt->get_expr() ) {
    1235                                 assert( returnStmt->get_expr()->has_result() && ! returnStmt->get_expr()->get_result()->isVoid() );
    1236                                 delete returnStmt->get_expr();
    1237                                 returnStmt->set_expr( 0 );
    1238                         } else {
    1239                                 returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) );
     1198                void Pass1::premutate( ReturnStmt *returnStmt ) {
     1199                        if ( retval && returnStmt->expr ) {
     1200                                assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() );
     1201                                delete returnStmt->expr;
     1202                                returnStmt->expr = nullptr;
    12401203                        } // if
    1241                         return returnStmt;
    1242                 }
    1243 
    1244                 Type * Pass1::mutate( PointerType *pointerType ) {
    1245                         scopeTyVars.beginScope();
     1204                }
     1205
     1206                void Pass1::premutate( PointerType *pointerType ) {
     1207                        GuardScope( scopeTyVars );
    12461208                        makeTyVarMap( pointerType, scopeTyVars );
    1247 
    1248                         Type *ret = Mutator::mutate( pointerType );
    1249 
    1250                         scopeTyVars.endScope();
    1251                         return ret;
    1252                 }
    1253 
    1254                 Type * Pass1::mutate( FunctionType *functionType ) {
    1255                         scopeTyVars.beginScope();
     1209                }
     1210
     1211                void Pass1::premutate( FunctionType *functionType ) {
     1212                        GuardScope( scopeTyVars );
    12561213                        makeTyVarMap( functionType, scopeTyVars );
    1257 
    1258                         Type *ret = Mutator::mutate( functionType );
    1259 
    1260                         scopeTyVars.endScope();
    1261                         return ret;
    1262                 }
    1263 
    1264                 void Pass1::doBeginScope() {
     1214                }
     1215
     1216                void Pass1::beginScope() {
    12651217                        adapters.beginScope();
    12661218                }
    12671219
    1268                 void Pass1::doEndScope() {
     1220                void Pass1::endScope() {
    12691221                        adapters.endScope();
    12701222                }
     
    12931245                }
    12941246
    1295                 template< typename DeclClass >
    1296                 DeclClass * Pass2::handleDecl( DeclClass *decl ) {
    1297                         DeclClass *ret = static_cast< DeclClass *>( Parent::mutate( decl ) );
    1298 
    1299                         return ret;
    1300                 }
    1301 
    1302                 DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) {
    1303                         functionDecl = strict_dynamic_cast< FunctionDecl * > ( handleDecl( functionDecl ) );
     1247                DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {
    13041248                        FunctionType * ftype = functionDecl->get_functionType();
    13051249                        if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) {
     
    13251269                }
    13261270
    1327                 ObjectDecl * Pass2::mutate( ObjectDecl *objectDecl ) {
    1328                         return handleDecl( objectDecl );
    1329                 }
    1330 
    1331                 template< typename AggDecl >
    1332                 AggDecl * Pass2::handleAggDecl( AggDecl * aggDecl ) {
     1271                void Pass2::premutate( StructDecl * ) {
    13331272                        // prevent tyVars from leaking into containing scope
    1334                         scopeTyVars.beginScope();
    1335                         Parent::mutate( aggDecl );
    1336                         scopeTyVars.endScope();
    1337                         return aggDecl;
    1338                 }
    1339 
    1340                 StructDecl * Pass2::mutate( StructDecl *aggDecl ) {
    1341                         return handleAggDecl( aggDecl );
    1342                 }
    1343 
    1344                 UnionDecl * Pass2::mutate( UnionDecl *aggDecl ) {
    1345                         return handleAggDecl( aggDecl );
    1346                 }
    1347 
    1348                 TraitDecl * Pass2::mutate( TraitDecl *aggDecl ) {
    1349                         return handleAggDecl( aggDecl );
    1350                 }
    1351 
    1352                 TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
     1273                        GuardScope( scopeTyVars );
     1274                }
     1275
     1276                void Pass2::premutate( UnionDecl * ) {
     1277                        // prevent tyVars from leaking into containing scope
     1278                        GuardScope( scopeTyVars );
     1279                }
     1280
     1281                void Pass2::premutate( TraitDecl * ) {
     1282                        // prevent tyVars from leaking into containing scope
     1283                        GuardScope( scopeTyVars );
     1284                }
     1285
     1286                void Pass2::premutate( TypeDecl *typeDecl ) {
    13531287                        addToTyVarMap( typeDecl, scopeTyVars );
    1354                         if ( typeDecl->get_base() ) {
    1355                                 return handleDecl( typeDecl );
    1356                         } else {
    1357                                 return dynamic_cast<TypeDecl*>( Parent::mutate( typeDecl ) );
    1358                         }
    1359                 }
    1360 
    1361                 TypedefDecl * Pass2::mutate( TypedefDecl *typedefDecl ) {
    1362                         return handleDecl( typedefDecl );
    1363                 }
    1364 
    1365                 Type * Pass2::mutate( PointerType *pointerType ) {
    1366                         scopeTyVars.beginScope();
     1288                }
     1289
     1290                void Pass2::premutate( PointerType *pointerType ) {
     1291                        GuardScope( scopeTyVars );
    13671292                        makeTyVarMap( pointerType, scopeTyVars );
    1368 
    1369                         Type *ret = Parent::mutate( pointerType );
    1370 
    1371                         scopeTyVars.endScope();
    1372                         return ret;
    1373                 }
    1374 
    1375                 Type *Pass2::mutate( FunctionType *funcType ) {
    1376                         scopeTyVars.beginScope();
    1377 
     1293                }
     1294
     1295                void Pass2::premutate( FunctionType *funcType ) {
     1296                        GuardScope( scopeTyVars );
    13781297                        makeTyVarMap( funcType, scopeTyVars );
    13791298
     
    14141333                                // move all assertions into parameter list
    14151334                                for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
    1416 //      *assert = (*assert)->acceptMutator( *this );
    14171335                                        // assertion parameters may not be used in body, pass along with unused attribute.
    14181336                                        (*assert)->get_attributes().push_back( new Attribute( "unused" ) );
     
    14501368                                                }
    14511369                                        }
    1452 
    14531370                                        seenTypes.insert( typeName );
    14541371                                }
     
    14581375                        funcType->get_parameters().splice( last, inferredParams );
    14591376                        addAdapters( funcType );
    1460                         mutateAll( funcType->get_returnVals(), *this );
    1461                         mutateAll( funcType->get_parameters(), *this );
    1462 
    1463                         scopeTyVars.endScope();
    1464                         return funcType;
    14651377                }
    14661378
     
    14681380
    14691381                PolyGenericCalculator::PolyGenericCalculator()
    1470                         : knownLayouts(), knownOffsets(), bufNamer( "_buf" ), scopeTyVars( TypeDecl::Data{} ) {}
     1382                        : knownLayouts(), knownOffsets(), bufNamer( "_buf" ) {}
    14711383
    14721384                void PolyGenericCalculator::beginTypeScope( Type *ty ) {
     
    18291741
    18301742                template< typename DeclClass >
    1831                 DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
    1832                         scopeTyVars.beginScope();
     1743                void Pass3::handleDecl( DeclClass * decl, Type * type ) {
     1744                        GuardScope( scopeTyVars );
    18331745                        makeTyVarMap( type, scopeTyVars );
    1834 
    1835                         DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
    1836                         // ScrubTyVars::scrub( decl, scopeTyVars );
    18371746                        ScrubTyVars::scrubAll( decl );
    1838 
    1839                         scopeTyVars.endScope();
    1840                         return ret;
    1841                 }
    1842 
    1843                 ObjectDecl * Pass3::mutate( ObjectDecl *objectDecl ) {
    1844                         return handleDecl( objectDecl, objectDecl->get_type() );
    1845                 }
    1846 
    1847                 DeclarationWithType * Pass3::mutate( FunctionDecl *functionDecl ) {
    1848                         return handleDecl( functionDecl, functionDecl->get_functionType() );
    1849                 }
    1850 
    1851                 TypedefDecl * Pass3::mutate( TypedefDecl *typedefDecl ) {
    1852                         return handleDecl( typedefDecl, typedefDecl->get_base() );
     1747                }
     1748
     1749                void Pass3::premutate( ObjectDecl * objectDecl ) {
     1750                        handleDecl( objectDecl, objectDecl->type );
     1751                }
     1752
     1753                void Pass3::premutate( FunctionDecl * functionDecl ) {
     1754                        handleDecl( functionDecl, functionDecl->type );
     1755                }
     1756
     1757                void Pass3::premutate( TypedefDecl * typedefDecl ) {
     1758                        handleDecl( typedefDecl, typedefDecl->base );
    18531759                }
    18541760
    18551761                /// Strips the members from a generic aggregate
    1856                 void stripGenericMembers(AggregateDecl* decl) {
    1857                         if ( ! decl->get_parameters().empty() ) decl->get_members().clear();
    1858                 }
    1859 
    1860                 Declaration *Pass3::mutate( StructDecl *structDecl ) {
     1762                void stripGenericMembers(AggregateDecl * decl) {
     1763                        if ( ! decl->parameters.empty() ) decl->members.clear();
     1764                }
     1765
     1766                void Pass3::premutate( StructDecl * structDecl ) {
    18611767                        stripGenericMembers( structDecl );
    1862                         return structDecl;
    1863                 }
    1864 
    1865                 Declaration *Pass3::mutate( UnionDecl *unionDecl ) {
     1768                }
     1769
     1770                void Pass3::premutate( UnionDecl * unionDecl ) {
    18661771                        stripGenericMembers( unionDecl );
    1867                         return unionDecl;
    1868                 }
    1869 
    1870                 TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) {
    1871 //   Initializer *init = 0;
    1872 //   std::list< Expression *> designators;
    1873 //   addToTyVarMap( typeDecl, scopeTyVars );
    1874 //   if ( typeDecl->get_base() ) {
    1875 //     init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
    1876 //   }
    1877 //   return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
    1878 
     1772                }
     1773
     1774                void Pass3::premutate( TypeDecl * typeDecl ) {
    18791775                        addToTyVarMap( typeDecl, scopeTyVars );
    1880                         return dynamic_cast<TypeDecl*>( Mutator::mutate( typeDecl ) );
    1881                 }
    1882 
    1883                 Type * Pass3::mutate( PointerType *pointerType ) {
    1884                         scopeTyVars.beginScope();
     1776                }
     1777
     1778                void Pass3::premutate( PointerType * pointerType ) {
     1779                        GuardScope( scopeTyVars );
    18851780                        makeTyVarMap( pointerType, scopeTyVars );
    1886 
    1887                         Type *ret = Mutator::mutate( pointerType );
    1888 
    1889                         scopeTyVars.endScope();
    1890                         return ret;
    1891                 }
    1892 
    1893                 Type * Pass3::mutate( FunctionType *functionType ) {
    1894                         scopeTyVars.beginScope();
     1781                }
     1782
     1783                void Pass3::premutate( FunctionType * functionType ) {
     1784                        GuardScope( scopeTyVars );
    18951785                        makeTyVarMap( functionType, scopeTyVars );
    1896 
    1897                         Type *ret = Mutator::mutate( functionType );
    1898 
    1899                         scopeTyVars.endScope();
    1900                         return ret;
    19011786                }
    19021787        } // anonymous namespace
  • src/GenPoly/Specialize.cc

    r201aeb9 rd67cdb7  
    2222#include <utility>                       // for pair
    2323
     24#include "Common/PassVisitor.h"
    2425#include "Common/SemanticError.h"        // for SemanticError
    2526#include "Common/UniqueName.h"           // for UniqueName
     
    2829#include "InitTweak/InitTweak.h"         // for isIntrinsicCallExpr
    2930#include "Parser/LinkageSpec.h"          // for C
    30 #include "PolyMutator.h"                 // for PolyMutator
    3131#include "ResolvExpr/FindOpenVars.h"     // for findOpenVars
    3232#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
     
    4343
    4444namespace GenPoly {
    45         class Specialize final : public PolyMutator {
    46           public:
    47                 using PolyMutator::mutate;
    48                 virtual Expression * mutate( ApplicationExpr *applicationExpr ) override;
    49                 virtual Expression * mutate( AddressExpr *castExpr ) override;
    50                 virtual Expression * mutate( CastExpr *castExpr ) override;
    51                 // virtual Expression * mutate( LogicalExpr *logicalExpr );
    52                 // virtual Expression * mutate( ConditionalExpr *conditionalExpr );
    53                 // virtual Expression * mutate( CommaExpr *commaExpr );
     45        struct Specialize final : public WithTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
     46                Expression * postmutate( ApplicationExpr *applicationExpr );
     47                Expression * postmutate( AddressExpr *castExpr );
     48                Expression * postmutate( CastExpr *castExpr );
    5449
    5550                void handleExplicitParams( ApplicationExpr *appExpr );
     
    204199        }
    205200
    206         struct EnvTrimmer : public Visitor {
     201        struct EnvTrimmer {
    207202                TypeSubstitution * env, * newEnv;
    208203                EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
    209                 virtual void visit( TypeDecl * tyDecl ) {
     204                void previsit( TypeDecl * tyDecl ) {
    210205                        // transfer known bindings for seen type variables
    211                         if ( Type * t = env->lookup( tyDecl->get_name() ) ) {
    212                                 newEnv->add( tyDecl->get_name(), t );
     206                        if ( Type * t = env->lookup( tyDecl->name ) ) {
     207                                newEnv->add( tyDecl->name, t );
    213208                        }
    214209                }
     
    219214                if ( env ) {
    220215                        TypeSubstitution * newEnv = new TypeSubstitution();
    221                         EnvTrimmer trimmer( env, newEnv );
     216                        PassVisitor<EnvTrimmer> trimmer( env, newEnv );
    222217                        expr->accept( trimmer );
    223218                        return newEnv;
     
    277272                std::string oldParamPrefix = paramPrefix;
    278273                paramPrefix += "p";
    279                 // save stmtsToAdd in oldStmts
     274                // save stmtsToAddBefore in oldStmts
    280275                std::list< Statement* > oldStmts;
    281                 oldStmts.splice( oldStmts.end(), stmtsToAdd );
    282                 mutate( appExpr );
     276                oldStmts.splice( oldStmts.end(), stmtsToAddBefore );
     277                appExpr->acceptMutator( *visitor );
    283278                paramPrefix = oldParamPrefix;
    284279                // write any statements added for recursive specializations into the thunk body
    285                 thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd );
    286                 // restore oldStmts into stmtsToAdd
    287                 stmtsToAdd.splice( stmtsToAdd.end(), oldStmts );
     280                thunkFunc->statements->kids.splice( thunkFunc->statements->kids.end(), stmtsToAddBefore );
     281                // restore oldStmts into stmtsToAddBefore
     282                stmtsToAddBefore.splice( stmtsToAddBefore.end(), oldStmts );
    288283
    289284                // add return (or valueless expression) to the thunk
    290285                Statement *appStmt;
    291                 if ( funType->get_returnVals().empty() ) {
     286                if ( funType->returnVals.empty() ) {
    292287                        appStmt = new ExprStmt( noLabels, appExpr );
    293288                } else {
    294289                        appStmt = new ReturnStmt( noLabels, appExpr );
    295290                } // if
    296                 thunkFunc->get_statements()->get_kids().push_back( appStmt );
     291                thunkFunc->statements->kids.push_back( appStmt );
    297292
    298293                // add thunk definition to queue of statements to add
    299                 stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) );
     294                stmtsToAddBefore.push_back( new DeclStmt( noLabels, thunkFunc ) );
    300295                // return address of thunk function as replacement expression
    301296                return new AddressExpr( new VariableExpr( thunkFunc ) );
     
    304299        void Specialize::handleExplicitParams( ApplicationExpr *appExpr ) {
    305300                // create thunks for the explicit parameters
    306                 assert( appExpr->get_function()->has_result() );
    307                 FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
     301                assert( appExpr->function->result );
     302                FunctionType *function = getFunctionType( appExpr->function->result );
    308303                assert( function );
    309304                std::list< DeclarationWithType* >::iterator formal;
    310305                std::list< Expression* >::iterator actual;
    311306                for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) {
    312                         *actual = doSpecialization( (*formal )->get_type(), *actual, &appExpr->get_inferParams() );
    313                 }
    314         }
    315 
    316         Expression * Specialize::mutate( ApplicationExpr *appExpr ) {
    317                 appExpr->get_function()->acceptMutator( *this );
    318                 mutateAll( appExpr->get_args(), *this );
    319 
     307                        *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->get_inferParams() );
     308                }
     309        }
     310
     311        Expression * Specialize::postmutate( ApplicationExpr *appExpr ) {
    320312                if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) {
    321313                        // create thunks for the inferred parameters
     
    331323        }
    332324
    333         Expression * Specialize::mutate( AddressExpr *addrExpr ) {
    334                 addrExpr->get_arg()->acceptMutator( *this );
    335                 assert( addrExpr->has_result() );
    336                 addrExpr->set_arg( doSpecialization( addrExpr->get_result(), addrExpr->get_arg() ) );
     325        Expression * Specialize::postmutate( AddressExpr *addrExpr ) {
     326                assert( addrExpr->result );
     327                addrExpr->set_arg( doSpecialization( addrExpr->result, addrExpr->arg ) );
    337328                return addrExpr;
    338329        }
    339330
    340         Expression * Specialize::mutate( CastExpr *castExpr ) {
    341                 castExpr->get_arg()->acceptMutator( *this );
    342                 if ( castExpr->get_result()->isVoid() ) {
     331        Expression * Specialize::postmutate( CastExpr *castExpr ) {
     332                if ( castExpr->result->isVoid() ) {
    343333                        // can't specialize if we don't have a return value
    344334                        return castExpr;
    345335                }
    346                 Expression *specialized = doSpecialization( castExpr->get_result(), castExpr->get_arg() );
    347                 if ( specialized != castExpr->get_arg() ) {
     336                Expression *specialized = doSpecialization( castExpr->result, castExpr->arg );
     337                if ( specialized != castExpr->arg ) {
    348338                        // assume here that the specialization incorporates the cast
    349339                        return specialized;
     
    353343        }
    354344
    355         // Removing these for now. Richard put these in for some reason, but it's not clear why.
    356         // In particular, copy constructors produce a comma expression, and with this code the parts
    357         // of that comma expression are not specialized, which causes problems.
    358 
    359         // Expression * Specialize::mutate( LogicalExpr *logicalExpr ) {
    360         //      return logicalExpr;
    361         // }
    362 
    363         // Expression * Specialize::mutate( ConditionalExpr *condExpr ) {
    364         //      return condExpr;
    365         // }
    366 
    367         // Expression * Specialize::mutate( CommaExpr *commaExpr ) {
    368         //      return commaExpr;
    369         // }
    370 
    371345        void convertSpecializations( std::list< Declaration* >& translationUnit ) {
    372                 Specialize spec;
     346                PassVisitor<Specialize> spec;
    373347                mutateAll( translationUnit, spec );
    374348        }
  • src/GenPoly/module.mk

    r201aeb9 rd67cdb7  
    66## file "LICENCE" distributed with Cforall.
    77##
    8 ## module.mk -- 
     8## module.mk --
    99##
    1010## Author           : Richard C. Bilson
     
    1717SRC += GenPoly/Box.cc \
    1818       GenPoly/GenPoly.cc \
    19        GenPoly/PolyMutator.cc \
    2019       GenPoly/ScrubTyVars.cc \
    2120       GenPoly/Lvalue.cc \
     
    2322       GenPoly/CopyParams.cc \
    2423       GenPoly/FindFunction.cc \
    25        GenPoly/DeclMutator.cc \
    2624       GenPoly/InstantiateGeneric.cc
  • src/InitTweak/FixInit.cc

    r201aeb9 rd67cdb7  
    3636#include "FixGlobalInit.h"             // for fixGlobalInit
    3737#include "GenInit.h"                   // for genCtorDtor
    38 #include "GenPoly/DeclMutator.h"       // for DeclMutator
    3938#include "GenPoly/GenPoly.h"           // for getFunctionType
    40 #include "GenPoly/PolyMutator.h"       // for PolyMutator
    4139#include "InitTweak.h"                 // for getFunctionName, getCallArg
    4240#include "Parser/LinkageSpec.h"        // for C, Spec, Cforall, isBuiltin
     
    4644#include "SymTab/Indexer.h"            // for Indexer
    4745#include "SymTab/Mangler.h"            // for Mangler
    48 #include "SynTree/AddStmtVisitor.h"    // for AddStmtVisitor
    4946#include "SynTree/Attribute.h"         // for Attribute
    5047#include "SynTree/Constant.h"          // for Constant
     
    5855#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    5956#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    60 #include "Tuples/Tuples.h"             // for isTtype
    6157
    6258bool ctordtorp = false; // print all debug
     
    187183                };
    188184
    189                 class FixCopyCtors final : public GenPoly::PolyMutator {
     185                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
    190186                  public:
    191187                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    194190                        static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
    195191
    196                         typedef GenPoly::PolyMutator Parent;
    197                         using Parent::mutate;
    198                         virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
    199                         virtual Expression * mutate( UniqueExpr * unqExpr ) override;
    200                         virtual Expression * mutate( StmtExpr * stmtExpr ) override;
     192                        Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     193                        void premutate( StmtExpr * stmtExpr );
     194                        void premutate( UniqueExpr * unqExpr );
    201195
    202196                        UnqCount & unqCount;
     
    243237                };
    244238
    245                 class FixCtorExprs final : public GenPoly::DeclMutator {
    246                   public:
     239                struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
    247240                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    248241                        static void fix( std::list< Declaration * > & translationUnit );
    249242
    250                         using GenPoly::DeclMutator::mutate;
    251                         virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
     243                        Expression * postmutate( ConstructorExpr * ctorExpr );
    252244                };
    253245        } // namespace
     
    316308
    317309                void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    318                         FixCopyCtors fixer( unqCount );
     310                        PassVisitor<FixCopyCtors> fixer( unqCount );
    319311                        mutateAll( translationUnit, fixer );
    320312                }
     
    326318
    327319                void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
    328                         FixCtorExprs fixer;
    329                         fixer.mutateDeclarationList( translationUnit );
     320                        PassVisitor<FixCtorExprs> fixer;
     321                        mutateAll( translationUnit, fixer );
    330322                }
    331323
     
    339331                                } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
    340332                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    341                                         assert( ftype );
     333                                        assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
    342334                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    343335                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
     
    368360                }
    369361
    370                 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    371                         return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    372                 }
     362                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
    373363
    374364                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     
    407397                        result = result->clone();
    408398                        env->apply( result );
    409                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     399                        ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
    410400                        tmp->get_type()->set_const( false );
    411401
     
    421411                                if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
    422412                        }
     413
     414                        // set a unique name for the temporary once it's certain the call is necessary
     415                        tmp->name = tempNamer.newName();
    423416
    424417                        // replace argument to function call with temporary
     
    450443                                result = result->clone();
    451444                                env->apply( result );
    452                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     445                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    453446                                ret->get_type()->set_const( false );
    454447                                impCpCtorExpr->get_returnDecls().push_back( ret );
    455448                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    456449                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    457                                         // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
     450                                        // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    458451                                        destructRet( ret, impCpCtorExpr );
    459452                                }
     
    472465                                result = result->clone();
    473466                                env->apply( result );
    474                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     467                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    475468                                ret->get_type()->set_const( false );
    476469                                stmtExpr->get_returnDecls().push_front( ret );
     
    509502                        } else {
    510503                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    511                                 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
     504                                unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), nullptr ) );
    512505                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
    513506                        }
     
    515508                }
    516509
    517                 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     510                Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    518511                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    519512
    520                         impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
    521513                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
    522514                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     
    525517                        // add all temporary declarations and their constructors
    526518                        for ( ObjectDecl * obj : tempDecls ) {
    527                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     519                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    528520                        } // for
    529521                        for ( ObjectDecl * obj : returnDecls ) {
    530                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     522                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    531523                        } // for
    532524
     
    536528                        } // for
    537529
    538                         // xxx - update to work with multiple return values
    539530                        ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
    540531                        Expression * callExpr = impCpCtorExpr->get_callExpr();
     
    569560                }
    570561
    571                 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
     562                void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
    572563                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    573564                        // since temporaries can be shared across sub-expressions, e.g.
    574565                        //   [A, A] f();
    575566                        //   g([A] x, [A] y);
    576                         //   f(g());
     567                        //   g(f());
    577568                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
     569                        // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
     570                        // to the outer context, rather than inside of the statement expression.
     571                        visit_children = false;
    578572                        std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    579573                        for ( Statement *& stmt : stmts ) {
    580                                 stmt = stmt->acceptMutator( *this );
     574                                stmt = stmt->acceptMutator( *visitor );
    581575                        } // for
    582                         // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
    583576                        assert( stmtExpr->get_result() );
    584577                        Type * result = stmtExpr->get_result();
    585578                        if ( ! result->isVoid() ) {
    586579                                for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
    587                                         stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     580                                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    588581                                } // for
    589582                                // add destructors after current statement
     
    592585                                } // for
    593586                                // must have a non-empty body, otherwise it wouldn't have a result
    594                                 CompoundStmt * body = stmtExpr->get_statements();
    595                                 assert( ! body->get_kids().empty() );
     587                                assert( ! stmts.empty() );
    596588                                assert( ! stmtExpr->get_returnDecls().empty() );
    597                                 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
     589                                stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    598590                                stmtExpr->get_returnDecls().clear();
    599591                                stmtExpr->get_dtors().clear();
     
    601593                        assert( stmtExpr->get_returnDecls().empty() );
    602594                        assert( stmtExpr->get_dtors().empty() );
    603                         return stmtExpr;
    604                 }
    605 
    606                 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
     595                }
     596
     597                void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
     598                        visit_children = false;
    607599                        unqCount[ unqExpr->get_id() ]--;
    608600                        static std::unordered_map< int, std::list< Statement * > > dtors;
    609601                        static std::unordered_map< int, UniqueExpr * > unqMap;
    610                         static std::unordered_set< int > addDeref;
    611602                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    612603                        if ( unqMap.count( unqExpr->get_id() ) ) {
     
    619610                                        stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    620611                                }
    621                                 if ( addDeref.count( unqExpr->get_id() ) ) {
    622                                         // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
    623                                         return UntypedExpr::createDeref( unqExpr );
    624                                 }
    625                                 return unqExpr;
    626                         }
    627                         FixCopyCtors fixer( unqCount );
     612                                return;
     613                        }
     614                        PassVisitor<FixCopyCtors> fixer( unqCount );
    628615                        unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
    629                         stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd );
     616                        stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
    630617                        unqMap[unqExpr->get_id()] = unqExpr;
    631618                        if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    632619                                stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    633620                        } else { // remember dtors for last instance of unique expr
    634                                 dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter;
    635                         }
    636                         if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
    637                                 // unique expression is now a dereference, because the inner expression is an lvalue returning function call.
    638                                 // Normalize the expression by dereferencing the unique expression, rather than the inner expression
    639                                 // (i.e. move the dereference out a level)
    640                                 assert( getFunctionName( deref ) == "*?" );
    641                                 unqExpr->set_expr( getCallArg( deref, 0 ) );
    642                                 getCallArg( deref, 0 ) = unqExpr;
    643                                 addDeref.insert( unqExpr->get_id() );
    644                                 return deref;
    645                         }
    646                         return unqExpr;
     621                                dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
     622                        }
     623                        return;
    647624                }
    648625
     
    819796                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    820797                                        Statement * dtor = ctorInit->get_dtor();
     798                                        // don't need to call intrinsic dtor, because it does nothing, but
     799                                        // non-intrinsic dtors must be called
    821800                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    822                                                 // don't need to call intrinsic dtor, because it does nothing, but
    823                                                 // non-intrinsic dtors must be called
     801                                                // set dtor location to the object's location for error messages
     802                                                ctorInit->dtor->location = objDecl->location;
    824803                                                reverseDeclOrder.front().push_front( objDecl );
    825804                                        } // if
     
    1012991                                        // skip non-DWT members
    1013992                                        if ( ! field ) continue;
     993                                        // skip non-constructable members
     994                                        if ( ! tryConstruct( field ) ) continue;
    1014995                                        // skip handled members
    1015996                                        if ( ! unhandled.count( field ) ) continue;
     
    11421123                }
    11431124
    1144                 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
     1125                Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
    11451126                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    11461127                        // xxx - is the size check necessary?
     
    11481129
    11491130                        // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
    1150                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
    1151                         addDeclaration( tmp );
     1131                        ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );
     1132                        declsToAddBefore.push_back( tmp );
    11521133
    11531134                        // xxx - this can be TupleAssignExpr now. Need to properly handle this case.
     
    11581139                        delete ctorExpr;
    11591140
     1141                        // build assignment and replace constructor's first argument with new temporary
    11601142                        Expression *& firstArg = callExpr->get_args().front();
    1161 
    1162                         // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away.
    1163 
    1164                         // generate the type of assignment operator using the type of tmp minus any reference types
    1165                         Type * type = tmp->get_type()->stripReferences();
    1166                         FunctionType * ftype = SymTab::genAssignType( type );
    1167 
    1168                         // generate fake assignment decl and call it using &tmp and &firstArg
    1169                         // since tmp is guaranteed to be a reference and we want to assign pointers
    1170                         FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
    1171                         ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
    1172                         assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
    1173                         Expression * addrArg = new AddressExpr( firstArg );
    1174                         // if firstArg has type T&&, then &firstArg has type T*&.
    1175                         // Cast away the reference to a value type so that the argument
    1176                         // matches the assignment's parameter types
    1177                         if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
    1178                                 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
    1179                         }
    1180                         assign->get_args().push_back( addrArg );
     1143                        Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
    11811144                        firstArg = new VariableExpr( tmp );
     1145
     1146                        // resolve assignment and dispose of new env
     1147                        Expression * resolvedAssign = ResolvExpr::findVoidExpression( assign, indexer );
     1148                        delete resolvedAssign->env;
     1149                        resolvedAssign->env = nullptr;
     1150                        delete assign;
    11821151
    11831152                        // for constructor expr:
     
    11881157                        //   T & tmp;
    11891158                        //   &tmp = &x, ?{}(tmp), tmp
    1190                         CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
     1159                        CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    11911160                        commaExpr->set_env( env );
    11921161                        return commaExpr;
  • src/InitTweak/GenInit.cc

    r201aeb9 rd67cdb7  
    2626#include "Common/UniqueName.h"     // for UniqueName
    2727#include "Common/utility.h"        // for ValueGuard, maybeClone
    28 #include "GenPoly/DeclMutator.h"   // for DeclMutator
    2928#include "GenPoly/GenPoly.h"       // for getFunctionType, isPolyType
    3029#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::const_iter...
     
    6261        };
    6362
    64         struct CtorDtor : public WithGuards, public WithShortCircuiting  {
     63        struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor>  {
    6564                /// create constructor and destructor statements for object declarations.
    6665                /// the actual call statements will be added in after the resolver has run
     
    7574                // that need to be constructed or destructed
    7675                void previsit( StructDecl *aggregateDecl );
    77                 void previsit( __attribute__((unused)) UnionDecl    * aggregateDecl ) { visit_children = false; }
    78                 void previsit( __attribute__((unused)) EnumDecl     * aggregateDecl ) { visit_children = false; }
    79                 void previsit( __attribute__((unused)) TraitDecl    * aggregateDecl ) { visit_children = false; }
    80                 void previsit( __attribute__((unused)) TypeDecl     * typeDecl )      { visit_children = false; }
    81                 void previsit( __attribute__((unused)) TypedefDecl  * typeDecl )      { visit_children = false; }
    82                 void previsit( __attribute__((unused)) FunctionType * funcType )      { visit_children = false; }
     76                void previsit( AggregateDecl * ) { visit_children = false; }
     77                void previsit( NamedTypeDecl * ) { visit_children = false; }
     78                void previsit( FunctionType * ) { visit_children = false; }
    8379
    8480                void previsit( CompoundStmt * compoundStmt );
     
    9692        };
    9793
    98         class HoistArrayDimension final : public GenPoly::DeclMutator {
    99           public:
    100                 typedef GenPoly::DeclMutator Parent;
    101 
     94        struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
    10295                /// hoist dimension from array types in object declaration so that it uses a single
    10396                /// const variable of type size_t, so that side effecting array dimensions are only
     
    10598                static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    10699
    107           private:
    108                 using Parent::mutate;
    109 
    110                 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override;
    111                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
     100                void premutate( ObjectDecl * objectDecl );
     101                DeclarationWithType * postmutate( ObjectDecl * objectDecl );
     102                void premutate( FunctionDecl *functionDecl );
    112103                // should not traverse into any of these declarations to find objects
    113104                // that need to be constructed or destructed
    114                 virtual Declaration* mutate( StructDecl *aggregateDecl ) override { return aggregateDecl; }
    115                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; }
    116                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; }
    117                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; }
    118                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; }
    119                 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; }
    120 
    121                 virtual Type* mutate( FunctionType *funcType ) override { return funcType; }
     105                void premutate( AggregateDecl * ) { visit_children = false; }
     106                void premutate( NamedTypeDecl * ) { visit_children = false; }
     107                void premutate( FunctionType * ) { visit_children = false; }
    122108
    123109                void hoist( Type * type );
     
    128114
    129115        void genInit( std::list< Declaration * > & translationUnit ) {
    130                 ReturnFixer::makeReturnTemp( translationUnit );
     116                fixReturnStatements( translationUnit );
    131117                HoistArrayDimension::hoistArrayDimension( translationUnit );
    132118                CtorDtor::generateCtorDtor( translationUnit );
    133119        }
    134120
    135         void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {
     121        void fixReturnStatements( std::list< Declaration * > & translationUnit ) {
    136122                PassVisitor<ReturnFixer> fixer;
    137123                mutateAll( translationUnit, fixer );
     
    143129                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    144130                // is being returned
    145                 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
     131                if ( returnStmt->get_expr() && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
    146132                        // explicitly construct the return value using the return expression and the retVal object
    147133                        assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
     
    158144                GuardValue( funcName );
    159145
    160                 ftype = functionDecl->get_functionType();
    161                 funcName = functionDecl->get_name();
     146                ftype = functionDecl->type;
     147                funcName = functionDecl->name;
    162148        }
    163149
     
    165151        // which would be incorrect if it is a side-effecting computation.
    166152        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    167                 HoistArrayDimension hoister;
    168                 hoister.mutateDeclarationList( translationUnit );
    169         }
    170 
    171         DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
     153                PassVisitor<HoistArrayDimension> hoister;
     154                mutateAll( translationUnit, hoister );
     155        }
     156
     157        void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) {
     158                GuardValue( storageClasses );
    172159                storageClasses = objectDecl->get_storageClasses();
    173                 DeclarationWithType * temp = Parent::mutate( objectDecl );
     160        }
     161
     162        DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) {
    174163                hoist( objectDecl->get_type() );
    175                 return temp;
     164                return objectDecl;
    176165        }
    177166
     
    194183
    195184                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
    196                         addDeclaration( arrayDimension );
     185                        declsToAddBefore.push_back( arrayDimension );
    197186
    198187                        hoist( arrayType->get_base() );
     
    201190        }
    202191
    203         DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
    204                 ValueGuard< bool > oldInFunc( inFunction );
    205                 inFunction = true;
    206                 DeclarationWithType * decl = Parent::mutate( functionDecl );
    207                 return decl;
     192        void HoistArrayDimension::premutate( FunctionDecl * ) {
     193                GuardValue( inFunction );
    208194        }
    209195
     
    214200
    215201        bool CtorDtor::isManaged( Type * type ) const {
    216                 // at least for now, references are never constructed
     202                // references are never constructed
    217203                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    218204                // need to clear and reset qualifiers when determining if a type is managed
     
    221207                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    222208                        // tuple is also managed if any of its components are managed
    223                         if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
     209                        if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) {
    224210                                return true;
    225211                        }
     
    305291
    306292        void CtorDtor::previsit( FunctionDecl *functionDecl ) {
     293                visit_children = false;  // do not try and construct parameters or forall parameters
    307294                GuardValue( inFunction );
    308295                inFunction = true;
     
    318305                }
    319306
    320                 PassVisitor<CtorDtor> newCtorDtor;
    321                 newCtorDtor.pass = *this;
    322                 maybeAccept( functionDecl->get_statements(), newCtorDtor );
    323                 visit_children = false;  // do not try and construct parameters or forall parameters - must happen after maybeAccept
     307                maybeAccept( functionDecl->get_statements(), *visitor );
    324308        }
    325309
     
    340324        }
    341325
    342         void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt ) {
     326        void CtorDtor::previsit( CompoundStmt * ) {
    343327                GuardScope( managedTypes );
    344328        }
  • src/InitTweak/GenInit.h

    r201aeb9 rd67cdb7  
    2525        void genInit( std::list< Declaration * > & translationUnit );
    2626
    27   /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
    28   ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
     27        /// Converts return statements into copy constructor calls on the hidden return variable
     28        void fixReturnStatements( std::list< Declaration * > & translationUnit );
     29
     30        /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
     31        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
    2932
    3033        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
  • src/InitTweak/InitTweak.cc

    r201aeb9 rd67cdb7  
    1 #include <stddef.h>                // for NULL
    21#include <algorithm>               // for find, all_of
    32#include <cassert>                 // for assertf, assert, strict_dynamic_cast
     
    2322#include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
    2423#include "SynTree/Visitor.h"       // for Visitor, maybeAccept
     24#include "Tuples/Tuples.h"         // for Tuples::isTtype
    2525
    2626class UntypedValofExpr;
     
    184184                        callExpr->get_args().splice( callExpr->get_args().end(), args );
    185185
    186                         *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
     186                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr );
    187187
    188188                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
     
    250250        // To accomplish this, generate switch statement, consuming all of expander's elements
    251251        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    252                 if ( ! init ) return NULL;
     252                if ( ! init ) return nullptr;
    253253                CompoundStmt * block = new CompoundStmt( noLabels );
    254254                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
    255255                if ( block->get_kids().empty() ) {
    256256                        delete block;
    257                         return NULL;
     257                        return nullptr;
    258258                } else {
    259                         init = NULL; // init was consumed in creating the list init
     259                        init = nullptr; // init was consumed in creating the list init
    260260                        return block;
    261261                }
    262262        }
    263263
    264         Statement * ExprImpl::buildListInit( __attribute((unused)) UntypedExpr * dst, __attribute((unused)) std::list< Expression * > & indices ) {
    265                 return NULL;
     264        Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
     265                return nullptr;
    266266        }
    267267
     
    270270        }
    271271
    272         bool tryConstruct( ObjectDecl * objDecl ) {
     272        bool tryConstruct( DeclarationWithType * dwt ) {
     273                ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
     274                if ( ! objDecl ) return false;
    273275                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    274                         (objDecl->get_init() == NULL ||
    275                                 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ))
    276                         && ! objDecl->get_storageClasses().is_extern;
     276                        (objDecl->get_init() == nullptr ||
     277                                ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() ))
     278                        && ! objDecl->get_storageClasses().is_extern
     279                        && isConstructable( objDecl->type );
     280        }
     281
     282        bool isConstructable( Type * type ) {
     283                return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type );
    277284        }
    278285
     
    314321                collectCtorDtorCalls( stmt, matches );
    315322                assert( matches.size() <= 1 );
    316                 return matches.size() == 1 ? matches.front() : NULL;
     323                return matches.size() == 1 ? matches.front() : nullptr;
    317324        }
    318325
     
    359366        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
    360367                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
    361                 if ( ! appExpr ) return NULL;
     368                if ( ! appExpr ) return nullptr;
    362369                DeclarationWithType * function = getCalledFunction( appExpr->get_function() );
    363370                assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() );
    364371                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    365372                // will call all member dtors, and some members may have a user defined dtor.
    366                 return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
     373                return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr;
    367374        }
    368375
     
    482489                        return refType->get_base();
    483490                } else {
    484                         return NULL;
     491                        return nullptr;
    485492                }
    486493        }
     
    488495        Type * isPointerType( Type * type ) {
    489496                if ( getPointerBase( type ) ) return type;
    490                 else return NULL;
     497                else return nullptr;
    491498        }
    492499
  • src/InitTweak/InitTweak.h

    r201aeb9 rd67cdb7  
    3333        std::list< Expression * > makeInitList( Initializer * init );
    3434
    35         /// True if the resolver should try to construct objDecl
    36         bool tryConstruct( ObjectDecl * objDecl );
     35        /// True if the resolver should try to construct dwt
     36        bool tryConstruct( DeclarationWithType * dwt );
     37
     38        /// True if the type can have a user-defined constructor
     39        bool isConstructable( Type * t );
    3740
    3841        /// True if the Initializer contains designations
  • src/Makefile.in

    r201aeb9 rd67cdb7  
    172172        GenPoly/driver_cfa_cpp-Box.$(OBJEXT) \
    173173        GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT) \
    174         GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT) \
    175174        GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT) \
    176175        GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT) \
     
    178177        GenPoly/driver_cfa_cpp-CopyParams.$(OBJEXT) \
    179178        GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \
    180         GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT) \
    181179        GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT) \
    182180        InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT) \
     
    253251        SynTree/driver_cfa_cpp-Visitor.$(OBJEXT) \
    254252        SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \
    255         SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT) \
    256253        SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
    257254        SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
     
    497494        ControlStruct/ForExprMutator.cc \
    498495        ControlStruct/ExceptTranslate.cc GenPoly/Box.cc \
    499         GenPoly/GenPoly.cc GenPoly/PolyMutator.cc \
    500         GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \
    501         GenPoly/CopyParams.cc GenPoly/FindFunction.cc \
    502         GenPoly/DeclMutator.cc GenPoly/InstantiateGeneric.cc \
     496        GenPoly/GenPoly.cc GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc \
     497        GenPoly/Specialize.cc GenPoly/CopyParams.cc \
     498        GenPoly/FindFunction.cc GenPoly/InstantiateGeneric.cc \
    503499        InitTweak/GenInit.cc InitTweak/FixInit.cc \
    504500        InitTweak/FixGlobalInit.cc InitTweak/InitTweak.cc \
     
    535531        SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \
    536532        SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \
    537         SynTree/AddStmtVisitor.cc SynTree/TypeSubstitution.cc \
    538         SynTree/Attribute.cc SynTree/VarExprReplacer.cc \
    539         Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
    540         Tuples/Explode.cc Virtual/ExpandCasts.cc
     533        SynTree/TypeSubstitution.cc SynTree/Attribute.cc \
     534        SynTree/VarExprReplacer.cc Tuples/TupleAssignment.cc \
     535        Tuples/TupleExpansion.cc Tuples/Explode.cc \
     536        Virtual/ExpandCasts.cc
    541537MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
    542538        ${cfa_cpplib_PROGRAMS}}
     
    717713GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT): GenPoly/$(am__dirstamp) \
    718714        GenPoly/$(DEPDIR)/$(am__dirstamp)
    719 GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \
    720         GenPoly/$(DEPDIR)/$(am__dirstamp)
    721715GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT): GenPoly/$(am__dirstamp) \
    722716        GenPoly/$(DEPDIR)/$(am__dirstamp)
     
    729723GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT):  \
    730724        GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
    731 GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \
    732         GenPoly/$(DEPDIR)/$(am__dirstamp)
    733725GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT):  \
    734726        GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
     
    929921SynTree/driver_cfa_cpp-Mutator.$(OBJEXT): SynTree/$(am__dirstamp) \
    930922        SynTree/$(DEPDIR)/$(am__dirstamp)
    931 SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT):  \
    932         SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    933923SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT):  \
    934924        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     
    1008998@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Po@am__quote@
    1009999@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Po@am__quote@
    1010 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Po@am__quote@
    10111000@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po@am__quote@
    10121001@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po@am__quote@
    10131002@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po@am__quote@
    10141003@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Po@am__quote@
    1015 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po@am__quote@
    10161004@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po@am__quote@
    10171005@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po@am__quote@
     
    10561044@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Po@am__quote@
    10571045@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Po@am__quote@
    1058 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po@am__quote@
    10591046@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po@am__quote@
    10601047@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Po@am__quote@
     
    14501437@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-GenPoly.obj `if test -f 'GenPoly/GenPoly.cc'; then $(CYGPATH_W) 'GenPoly/GenPoly.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/GenPoly.cc'; fi`
    14511438
    1452 GenPoly/driver_cfa_cpp-PolyMutator.o: GenPoly/PolyMutator.cc
    1453 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-PolyMutator.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo -c -o GenPoly/driver_cfa_cpp-PolyMutator.o `test -f 'GenPoly/PolyMutator.cc' || echo '$(srcdir)/'`GenPoly/PolyMutator.cc
    1454 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po
    1455 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/PolyMutator.cc' object='GenPoly/driver_cfa_cpp-PolyMutator.o' libtool=no @AMDEPBACKSLASH@
    1456 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1457 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-PolyMutator.o `test -f 'GenPoly/PolyMutator.cc' || echo '$(srcdir)/'`GenPoly/PolyMutator.cc
    1458 
    1459 GenPoly/driver_cfa_cpp-PolyMutator.obj: GenPoly/PolyMutator.cc
    1460 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-PolyMutator.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo -c -o GenPoly/driver_cfa_cpp-PolyMutator.obj `if test -f 'GenPoly/PolyMutator.cc'; then $(CYGPATH_W) 'GenPoly/PolyMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/PolyMutator.cc'; fi`
    1461 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po
    1462 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/PolyMutator.cc' object='GenPoly/driver_cfa_cpp-PolyMutator.obj' libtool=no @AMDEPBACKSLASH@
    1463 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1464 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-PolyMutator.obj `if test -f 'GenPoly/PolyMutator.cc'; then $(CYGPATH_W) 'GenPoly/PolyMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/PolyMutator.cc'; fi`
    1465 
    14661439GenPoly/driver_cfa_cpp-ScrubTyVars.o: GenPoly/ScrubTyVars.cc
    14671440@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-ScrubTyVars.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Tpo -c -o GenPoly/driver_cfa_cpp-ScrubTyVars.o `test -f 'GenPoly/ScrubTyVars.cc' || echo '$(srcdir)/'`GenPoly/ScrubTyVars.cc
     
    15341507@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-FindFunction.obj `if test -f 'GenPoly/FindFunction.cc'; then $(CYGPATH_W) 'GenPoly/FindFunction.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/FindFunction.cc'; fi`
    15351508
    1536 GenPoly/driver_cfa_cpp-DeclMutator.o: GenPoly/DeclMutator.cc
    1537 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-DeclMutator.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo -c -o GenPoly/driver_cfa_cpp-DeclMutator.o `test -f 'GenPoly/DeclMutator.cc' || echo '$(srcdir)/'`GenPoly/DeclMutator.cc
    1538 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Po
    1539 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/DeclMutator.cc' object='GenPoly/driver_cfa_cpp-DeclMutator.o' libtool=no @AMDEPBACKSLASH@
    1540 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1541 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-DeclMutator.o `test -f 'GenPoly/DeclMutator.cc' || echo '$(srcdir)/'`GenPoly/DeclMutator.cc
    1542 
    1543 GenPoly/driver_cfa_cpp-DeclMutator.obj: GenPoly/DeclMutator.cc
    1544 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-DeclMutator.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo -c -o GenPoly/driver_cfa_cpp-DeclMutator.obj `if test -f 'GenPoly/DeclMutator.cc'; then $(CYGPATH_W) 'GenPoly/DeclMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/DeclMutator.cc'; fi`
    1545 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Po
    1546 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='GenPoly/DeclMutator.cc' object='GenPoly/driver_cfa_cpp-DeclMutator.obj' libtool=no @AMDEPBACKSLASH@
    1547 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1548 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-DeclMutator.obj `if test -f 'GenPoly/DeclMutator.cc'; then $(CYGPATH_W) 'GenPoly/DeclMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/DeclMutator.cc'; fi`
    1549 
    15501509GenPoly/driver_cfa_cpp-InstantiateGeneric.o: GenPoly/InstantiateGeneric.cc
    15511510@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
     
    25832542@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    25842543@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Mutator.obj `if test -f 'SynTree/Mutator.cc'; then $(CYGPATH_W) 'SynTree/Mutator.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Mutator.cc'; fi`
    2585 
    2586 SynTree/driver_cfa_cpp-AddStmtVisitor.o: SynTree/AddStmtVisitor.cc
    2587 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddStmtVisitor.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.o `test -f 'SynTree/AddStmtVisitor.cc' || echo '$(srcdir)/'`SynTree/AddStmtVisitor.cc
    2588 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po
    2589 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AddStmtVisitor.cc' object='SynTree/driver_cfa_cpp-AddStmtVisitor.o' libtool=no @AMDEPBACKSLASH@
    2590 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2591 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.o `test -f 'SynTree/AddStmtVisitor.cc' || echo '$(srcdir)/'`SynTree/AddStmtVisitor.cc
    2592 
    2593 SynTree/driver_cfa_cpp-AddStmtVisitor.obj: SynTree/AddStmtVisitor.cc
    2594 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddStmtVisitor.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.obj `if test -f 'SynTree/AddStmtVisitor.cc'; then $(CYGPATH_W) 'SynTree/AddStmtVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddStmtVisitor.cc'; fi`
    2595 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po
    2596 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/AddStmtVisitor.cc' object='SynTree/driver_cfa_cpp-AddStmtVisitor.obj' libtool=no @AMDEPBACKSLASH@
    2597 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2598 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.obj `if test -f 'SynTree/AddStmtVisitor.cc'; then $(CYGPATH_W) 'SynTree/AddStmtVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddStmtVisitor.cc'; fi`
    25992544
    26002545SynTree/driver_cfa_cpp-TypeSubstitution.o: SynTree/TypeSubstitution.cc
  • src/Parser/StatementNode.cc

    r201aeb9 rd67cdb7  
    234234                target,
    235235                maybeMoveBuild<Statement >( stmt ),
    236                 maybeMoveBuild<Expression>( when )
     236                notZeroExpr( maybeMoveBuild<Expression>( when ) )
    237237        });
    238238
     
    250250        delete targetExpr;
    251251
    252         node->clauses.push_back( WaitForStmt::Clause{
     252        node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{
    253253                std::move( target ),
    254254                maybeMoveBuild<Statement >( stmt ),
    255                 maybeMoveBuild<Expression>( when )
     255                notZeroExpr( maybeMoveBuild<Expression>( when ) )
    256256        });
    257257
     
    265265                node->timeout.time      = maybeMoveBuild<Expression>( timeout );
    266266                node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
    267                 node->timeout.condition = maybeMoveBuild<Expression>( when    );
     267                node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    268268        }
    269269        else {
    270                 node->orelse.statement  = maybeMoveBuild<Statement >( stmt    );
    271                 node->orelse.condition  = maybeMoveBuild<Expression>( when    );
     270                node->orelse.statement  = maybeMoveBuild<Statement >( stmt );
     271                node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    272272        }
    273273
     
    280280        node->timeout.time      = maybeMoveBuild<Expression>( timeout );
    281281        node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
    282         node->timeout.condition = maybeMoveBuild<Expression>( when    );
     282        node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    283283
    284284        node->orelse.statement = maybeMoveBuild<Statement >( else_stmt );
    285         node->orelse.condition = maybeMoveBuild<Expression>( else_when );
     285        node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( else_when ) );
    286286
    287287        return node;
    288288}
    289 
    290 // WaitForStmt::Target build_waitfor( const std::string * name, ExpressionNode * arguments ) {
    291 //       return WaitForStmt::Clause{
    292 
    293 //       };
    294 // }
    295289
    296290Statement *build_compound( StatementNode *first ) {
  • src/Parser/parserutility.cc

    r201aeb9 rd67cdb7  
    2929
    3030Expression *notZeroExpr( Expression *orig ) {
     31        if( !orig ) return nullptr;
    3132        UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) );
    3233        comparison->get_args().push_back( orig );
  • src/ResolvExpr/AlternativeFinder.cc

    r201aeb9 rd67cdb7  
    144144                        expr->get_result()->accept( global_renamer );
    145145                }
    146 
    147                 void referenceToRvalueConversion( Expression *& expr ) {
    148                         if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
    149                                 // cast away reference from expr
    150                                 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
    151                         }
    152                 }
    153146        } // namespace
     147
     148        void referenceToRvalueConversion( Expression *& expr ) {
     149                if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
     150                        // cast away reference from expr
     151                        expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
     152                }
     153        }
    154154
    155155        template< typename InputIterator, typename OutputIterator >
  • src/ResolvExpr/AlternativeFinder.h

    r201aeb9 rd67cdb7  
    5050                const SymTab::Indexer &get_indexer() const { return indexer; }
    5151                const TypeEnvironment &get_environ() const { return env; }
     52
     53                /// Runs a new alternative finder on each element in [begin, end)
     54                /// and writes each alternative finder to out.
     55                template< typename InputIterator, typename OutputIterator >
     56                void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
    5257          private:
    5358                virtual void visit( ApplicationExpr *applicationExpr );
     
    8186                virtual void visit( StmtExpr *stmtExpr );
    8287                virtual void visit( UntypedInitExpr *initExpr );
    83                 /// Runs a new alternative finder on each element in [begin, end)
    84                 /// and writes each alternative finder to out.
    85                 template< typename InputIterator, typename OutputIterator >
    86                 void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
    8788
    8889                /// Adds alternatives for anonymous members
     
    108109
    109110        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
     111        void referenceToRvalueConversion( Expression *& expr );
    110112
    111113        template< typename InputIterator, typename OutputIterator >
  • src/ResolvExpr/Resolver.cc

    r201aeb9 rd67cdb7  
    4040#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    4141#include "typeops.h"                     // for extractResultType
     42#include "Unify.h"                       // for unify
    4243
    4344using namespace std;
     
    7172                void previsit( ThrowStmt *throwStmt );
    7273                void previsit( CatchStmt *catchStmt );
     74                void previsit( WaitForStmt * stmt );
    7375
    7476                void previsit( SingleInit *singleInit );
     
    9395                PassVisitor<Resolver> resolver;
    9496                acceptAll( translationUnit, resolver );
     97        }
     98
     99        void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
     100                PassVisitor<Resolver> resolver( indexer );
     101                maybeAccept( decl, resolver );
    95102        }
    96103
     
    116123        }
    117124
     125        Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     126                TypeEnvironment env;
     127                AlternativeFinder finder( indexer, env );
     128                finder.find( untyped );
     129                #if 0
     130                if ( finder.get_alternatives().size() != 1 ) {
     131                        std::cout << "untyped expr is ";
     132                        untyped->print( std::cout );
     133                        std::cout << std::endl << "alternatives are:";
     134                        for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
     135                                i->print( std::cout );
     136                        } // for
     137                } // if
     138                #endif
     139                assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
     140                Alternative &choice = finder.get_alternatives().front();
     141                Expression *newExpr = choice.expr->clone();
     142                finishExpr( newExpr, choice.env );
     143                return newExpr;
     144        }
     145
    118146        namespace {
    119                 Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
    120                         TypeEnvironment env;
    121                         AlternativeFinder finder( indexer, env );
    122                         finder.find( untyped );
    123 #if 0
    124                         if ( finder.get_alternatives().size() != 1 ) {
    125                                 std::cout << "untyped expr is ";
    126                                 untyped->print( std::cout );
    127                                 std::cout << std::endl << "alternatives are:";
    128                                 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    129                                         i->print( std::cout );
    130                                 } // for
    131                         } // if
    132 #endif
    133                         assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
    134                         Alternative &choice = finder.get_alternatives().front();
    135                         Expression *newExpr = choice.expr->clone();
    136                         finishExpr( newExpr, choice.env );
    137                         return newExpr;
    138                 }
    139 
    140147                bool isIntegralType( Type *type ) {
    141148                        if ( dynamic_cast< EnumInstType * >( type ) ) {
     
    391398        }
    392399
     400        inline void resolveAsIf( Expression *& expr, SymTab::Indexer & indexer ) {
     401                if( !expr ) return;
     402                Expression * newExpr = findSingleExpression( expr, indexer );
     403                delete expr;
     404                expr = newExpr;
     405        }
     406
     407        inline void resolveAsType( Expression *& expr, Type * type, SymTab::Indexer & indexer ) {
     408                if( !expr ) return;
     409                Expression * newExpr = findSingleExpression( new CastExpr( expr, type ), indexer );
     410                delete expr;
     411                expr = newExpr;
     412        }
     413
     414        template< typename iterator_t >
     415        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
     416                while( it != end && !(*it)->get_type()->get_mutex() ) {
     417                        it++;
     418                }
     419
     420                return it != end;
     421        }
     422
     423        void Resolver::previsit( WaitForStmt * stmt ) {
     424                visit_children = false;
     425
     426                // Resolve all clauses first
     427                for( auto& clause : stmt->clauses ) {
     428
     429                        TypeEnvironment env;
     430                        AlternativeFinder funcFinder( indexer, env );
     431
     432                        // Find all alternatives for a function in canonical form
     433                        funcFinder.findWithAdjustment( clause.target.function );
     434
     435                        if ( funcFinder.get_alternatives().empty() ) {
     436                                stringstream ss;
     437                                ss << "Use of undeclared indentifier '";
     438                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
     439                                ss << "' in call to waitfor";
     440                                throw SemanticError( ss.str() );
     441                        }
     442
     443                        // Find all alternatives for all arguments in canonical form
     444                        std::list< AlternativeFinder > argAlternatives;
     445                        funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
     446
     447                        // List all combinations of arguments
     448                        std::list< AltList > possibilities;
     449                        combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
     450
     451                        AltList                func_candidates;
     452                        std::vector< AltList > args_candidates;
     453
     454                        // For every possible function :
     455                        //      try matching the arguments to the parameters
     456                        //      not the other way around because we have more arguments than parameters
     457                        SemanticError errors;
     458                        for ( Alternative & func : funcFinder.get_alternatives() ) {
     459                                try {
     460                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
     461                                        if( !pointer ) {
     462                                                throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
     463                                        }
     464
     465                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
     466                                        if( !function ) {
     467                                                throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
     468                                        }
     469
     470
     471                                        {
     472                                                auto param     = function->parameters.begin();
     473                                                auto param_end = function->parameters.end();
     474
     475                                                if( !advance_to_mutex( param, param_end ) ) {
     476                                                        throw SemanticError("candidate function not viable: no mutex parameters\n", function);
     477                                                }
     478                                        }
     479
     480                                        Alternative newFunc( func );
     481                                        // Strip reference from function
     482                                        referenceToRvalueConversion( newFunc.expr );
     483
     484                                        // For all the set of arguments we have try to match it with the parameter of the current function alternative
     485                                        for ( auto & argsList : possibilities ) {
     486
     487                                                try {
     488                                                        // Declare data structures need for resolution
     489                                                        OpenVarSet openVars;
     490                                                        AssertionSet resultNeed, resultHave;
     491                                                        TypeEnvironment resultEnv;
     492
     493                                                        // Load type variables from arguemnts into one shared space
     494                                                        simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
     495
     496                                                        // Make sure we don't widen any existing bindings
     497                                                        for ( auto & i : resultEnv ) {
     498                                                                i.allowWidening = false;
     499                                                        }
     500
     501                                                        // Find any unbound type variables
     502                                                        resultEnv.extractOpenVars( openVars );
     503
     504                                                        auto param     = function->parameters.begin();
     505                                                        auto param_end = function->parameters.end();
     506
     507                                                        // For every arguments of its set, check if it matches one of the parameter
     508                                                        // The order is important
     509                                                        for( auto & arg : argsList ) {
     510
     511                                                                // Ignore non-mutex arguments
     512                                                                if( !advance_to_mutex( param, param_end ) ) {
     513                                                                        // We ran out of parameters but still have arguments
     514                                                                        // this function doesn't match
     515                                                                        throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
     516                                                                }
     517
     518                                                                // Check if the argument matches the parameter type in the current scope
     519                                                                if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
     520                                                                        // Type doesn't match
     521                                                                        stringstream ss;
     522                                                                        ss << "candidate function not viable: no known convertion from '";
     523                                                                        arg.expr->get_result()->print( ss );
     524                                                                        ss << "' to '";
     525                                                                        (*param)->get_type()->print( ss );
     526                                                                        ss << "'\n";
     527                                                                        throw SemanticError(ss.str(), function);
     528                                                                }
     529
     530                                                                param++;
     531                                                        }
     532
     533                                                        // All arguments match !
     534
     535                                                        // Check if parameters are missing
     536                                                        if( advance_to_mutex( param, param_end ) ) {
     537                                                                // We ran out of arguments but still have parameters left
     538                                                                // this function doesn't match
     539                                                                throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
     540                                                        }
     541
     542                                                        // All parameters match !
     543
     544                                                        // Finish the expressions to tie in the proper environments
     545                                                        finishExpr( newFunc.expr, resultEnv );
     546                                                        for( Alternative & alt : argsList ) {
     547                                                                finishExpr( alt.expr, resultEnv );
     548                                                        }
     549
     550                                                        // This is a match store it and save it for later
     551                                                        func_candidates.push_back( newFunc );
     552                                                        args_candidates.push_back( argsList );
     553
     554                                                }
     555                                                catch( SemanticError &e ) {
     556                                                        errors.append( e );
     557                                                }
     558                                        }
     559                                }
     560                                catch( SemanticError &e ) {
     561                                        errors.append( e );
     562                                }
     563                        }
     564
     565                        // Make sure we got the right number of arguments
     566                        if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     567                        if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     568                        if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     569                        if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     570
     571
     572                        // Swap the results from the alternative with the unresolved values.
     573                        // Alternatives will handle deletion on destruction
     574                        std::swap( clause.target.function, func_candidates.front().expr );
     575                        for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
     576                                std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
     577                        }
     578
     579                        // Resolve the conditions as if it were an IfStmt
     580                        // Resolve the statments normally
     581                        resolveAsIf( clause.condition, this->indexer );
     582                        clause.statement->accept( *visitor );
     583                }
     584
     585
     586                if( stmt->timeout.statement ) {
     587                        // Resolve the timeout as an size_t for now
     588                        // Resolve the conditions as if it were an IfStmt
     589                        // Resolve the statments normally
     590                        resolveAsType( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
     591                        resolveAsIf  ( stmt->timeout.condition, this->indexer );
     592                        stmt->timeout.statement->accept( *visitor );
     593                }
     594
     595                if( stmt->orelse.statement ) {
     596                        // Resolve the conditions as if it were an IfStmt
     597                        // Resolve the statments normally
     598                        resolveAsIf( stmt->orelse.condition, this->indexer );
     599                        stmt->orelse.statement->accept( *visitor );
     600                }
     601        }
     602
    393603        template< typename T >
    394604        bool isCharType( T t ) {
  • src/ResolvExpr/Resolver.h

    r201aeb9 rd67cdb7  
    2929        /// Checks types and binds syntactic constructs to typed representations
    3030        void resolve( std::list< Declaration * > translationUnit );
     31        void resolveDecl( Declaration *, const SymTab::Indexer &indexer );
    3132        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
    3233        Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );
     34        Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer );
    3335        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    3436        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
  • src/ResolvExpr/TypeEnvironment.cc

    r201aeb9 rd67cdb7  
    123123                for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    124124                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    125 ///       std::cout << "adding " << *theVar;
     125///       std::cerr << "adding " << *theVar;
    126126                                if ( theClass->type ) {
    127 ///         std::cout << " bound to ";
    128 ///         theClass->type->print( std::cout );
    129 ///         std::cout << std::endl;
     127///         std::cerr << " bound to ";
     128///         theClass->type->print( std::cerr );
     129///         std::cerr << std::endl;
    130130                                        sub.add( *theVar, theClass->type );
    131131                                } else if ( theVar != theClass->vars.begin() ) {
    132132                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
    133 ///         std::cout << " bound to variable " << *theClass->vars.begin() << std::endl;
     133///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
    134134                                        sub.add( *theVar, newTypeInst );
    135135                                        delete newTypeInst;
  • src/SymTab/Autogen.cc

    r201aeb9 rd67cdb7  
    1616#include "Autogen.h"
    1717
    18 #include <cstddef>                 // for NULL
    1918#include <algorithm>               // for count_if
    2019#include <cassert>                 // for strict_dynamic_cast, assert, assertf
     
    2726#include "AddVisit.h"              // for addVisit
    2827#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
     28#include "Common/PassVisitor.h"    // for PassVisitor
    2929#include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
    3030#include "Common/utility.h"        // for cloneAll, operator+
    31 #include "GenPoly/DeclMutator.h"   // for DeclMutator
    3231#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
     32#include "InitTweak/GenInit.h"     // for fixReturnStatements
     33#include "ResolvExpr/Resolver.h"   // for resolveDecl
    3334#include "SymTab/Mangler.h"        // for Mangler
    3435#include "SynTree/Attribute.h"     // For Attribute
     
    5354        };
    5455
    55         class AutogenerateRoutines final : public Visitor {
    56             template< typename Visitor >
    57             friend void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
    58             template< typename Visitor >
    59             friend void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor );
    60           public:
    61                 std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
    62 
    63                 typedef Visitor Parent;
    64                 using Parent::visit;
    65 
     56        struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting {
    6657                AutogenerateRoutines();
    6758
    68                 virtual void visit( EnumDecl *enumDecl );
    69                 virtual void visit( StructDecl *structDecl );
    70                 virtual void visit( UnionDecl *structDecl );
    71                 virtual void visit( TypeDecl *typeDecl );
    72                 virtual void visit( TraitDecl *ctxDecl );
    73                 virtual void visit( FunctionDecl *functionDecl );
    74 
    75                 virtual void visit( FunctionType *ftype );
    76                 virtual void visit( PointerType *ftype );
    77 
    78                 virtual void visit( CompoundStmt *compoundStmt );
    79                 virtual void visit( SwitchStmt *switchStmt );
     59                void previsit( EnumDecl * enumDecl );
     60                void previsit( StructDecl * structDecl );
     61                void previsit( UnionDecl * structDecl );
     62                void previsit( TypeDecl * typeDecl );
     63                void previsit( TraitDecl * traitDecl );
     64                void previsit( FunctionDecl * functionDecl );
     65
     66                void previsit( FunctionType * ftype );
     67                void previsit( PointerType * ptype );
     68
     69                void previsit( CompoundStmt * compoundStmt );
    8070
    8171          private:
    82                 template< typename StmtClass > void visitStatement( StmtClass *stmt );
    83 
    84                 std::list< Declaration * > declsToAdd, declsToAddAfter;
    85                 std::set< std::string > structsDone;
     72                GenPoly::ScopedSet< std::string > structsDone;
    8673                unsigned int functionNesting = 0;     // current level of nested functions
    8774                /// Note: the following maps could be ScopedSets, but it should be easier to work
     
    9380
    9481        /// generates routines for tuple types.
    95         /// Doesn't really need to be a mutator, but it's easier to reuse DeclMutator than it is to use AddVisit
    96         /// or anything we currently have that supports adding new declarations for visitors
    97         class AutogenTupleRoutines : public GenPoly::DeclMutator {
    98           public:
    99                 typedef GenPoly::DeclMutator Parent;
    100                 using Parent::mutate;
    101 
    102                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    103 
    104                 virtual Type * mutate( TupleType *tupleType );
    105 
    106                 virtual CompoundStmt * mutate( CompoundStmt *compoundStmt );
     82        struct AutogenTupleRoutines : public WithDeclsToAdd, public WithVisitorRef<AutogenTupleRoutines>, public WithGuards, public WithShortCircuiting {
     83                void previsit( FunctionDecl *functionDecl );
     84
     85                void postvisit( TupleType *tupleType );
     86
     87                void previsit( CompoundStmt *compoundStmt );
    10788
    10889          private:
     
    11293
    11394        void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
    114                 AutogenerateRoutines generator;
    115                 acceptAndAdd( translationUnit, generator );
     95                PassVisitor<AutogenerateRoutines> generator;
     96                acceptAll( translationUnit, generator );
    11697
    11798                // needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc.
    11899                // AutogenTupleRoutines tupleGenerator;
    119                 // tupleGenerator.mutateDeclarationList( translationUnit );
     100                // acceptAll( translationUnit, tupleGenerator );
    120101        }
    121102
    122103        bool isUnnamedBitfield( ObjectDecl * obj ) {
    123                 return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
     104                return obj != nullptr && obj->get_name() == "" && obj->get_bitfieldWidth() != nullptr;
    124105        }
    125106
     
    128109                FunctionDecl * decl = functionDecl->clone();
    129110                delete decl->get_statements();
    130                 decl->set_statements( NULL );
     111                decl->set_statements( nullptr );
    131112                declsToAdd.push_back( decl );
    132113                decl->fixUniqueId();
     
    339320                                assert( ! func->get_functionType()->get_parameters().empty() );
    340321                                ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
    341                                 ObjectDecl * srcParam = NULL;
     322                                ObjectDecl * srcParam = nullptr;
    342323                                if ( func->get_functionType()->get_parameters().size() == 2 ) {
    343324                                        srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
     
    346327                                assert( dstParam );
    347328
    348                                 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
     329                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr;
    349330                                makeStructMemberOp( dstParam, srcselect, field, func, forward );
    350331                        } // if
     
    385366                                } else {
    386367                                        // no matching parameter, initialize field with default ctor
    387                                         makeStructMemberOp( dstParam, NULL, field, func );
     368                                        makeStructMemberOp( dstParam, nullptr, field, func );
    388369                                }
    389370                        }
     
    401382        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {
    402383                // Builtins do not use autogeneration.
    403                 if ( aggregateDecl->get_linkage() == LinkageSpec::BuiltinCFA ||
    404                          aggregateDecl->get_linkage() == LinkageSpec::BuiltinC ) {
     384                if ( LinkageSpec::isBuiltin( aggregateDecl->get_linkage() ) ) {
    405385                        return;
    406386                }
    407387
    408388                // Make function polymorphic in same parameters as generic struct, if applicable
    409                 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
     389                const std::list< TypeDecl * > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    410390
    411391                // generate each of the functions based on the supplied FuncData objects
     
    572552                // the order here determines the order that these functions are generated.
    573553                // assignment should come last since it uses copy constructor in return.
    574                 data.push_back( FuncData( "?{}", genDefaultType, constructable ) );
    575                 data.push_back( FuncData( "?{}", genCopyType, copyable ) );
    576                 data.push_back( FuncData( "^?{}", genDefaultType, destructable ) );
    577                 data.push_back( FuncData( "?=?", genAssignType, assignable ) );
    578         }
    579 
    580         void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
     554                data.emplace_back( "?{}", genDefaultType, constructable );
     555                data.emplace_back( "?{}", genCopyType, copyable );
     556                data.emplace_back( "^?{}", genDefaultType, destructable );
     557                data.emplace_back( "?=?", genAssignType, assignable );
     558        }
     559
     560        void AutogenerateRoutines::previsit( EnumDecl * enumDecl ) {
     561                visit_children = false;
    581562                if ( ! enumDecl->get_members().empty() ) {
    582563                        EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
     
    586567        }
    587568
    588         void AutogenerateRoutines::visit( StructDecl *structDecl ) {
    589                 if ( structDecl->has_body() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
    590                         StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    591                         for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {
     569        void AutogenerateRoutines::previsit( StructDecl * structDecl ) {
     570                visit_children = false;
     571                if ( structDecl->has_body() && structsDone.find( structDecl->name ) == structsDone.end() ) {
     572                        StructInstType structInst( Type::Qualifiers(), structDecl->name );
     573                        for ( TypeDecl * typeDecl : structDecl->parameters ) {
    592574                                // need to visit assertions so that they are added to the appropriate maps
    593                                 acceptAll( typeDecl->get_assertions(), *this );
    594                                 structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
     575                                acceptAll( typeDecl->assertions, *visitor );
     576                                structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) );
    595577                        }
    596578                        structInst.set_baseStruct( structDecl );
    597579                        makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data );
    598                         structsDone.insert( structDecl->get_name() );
     580                        structsDone.insert( structDecl->name );
    599581                } // if
    600582        }
    601583
    602         void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
     584        void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) {
     585                visit_children = false;
    603586                if ( ! unionDecl->get_members().empty() ) {
    604587                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
     
    619602
    620603        // generate ctor/dtors/assign for typedecls, e.g., otype T = int *;
    621         void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
     604        void AutogenerateRoutines::previsit( TypeDecl * typeDecl ) {
     605                visit_children = false;
    622606                if ( ! typeDecl->base ) return;
    623607
     
    664648        }
    665649
    666         void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
    667                 for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
    668                         statements.insert( i, new DeclStmt( noLabels, *decl ) );
    669                 } // for
    670                 declsToAdd.clear();
    671         }
    672 
    673         void AutogenerateRoutines::visit( FunctionType *) {
     650        void AutogenerateRoutines::previsit( FunctionType *) {
    674651                // ensure that we don't add assignment ops for types defined as part of the function
    675         }
    676 
    677         void AutogenerateRoutines::visit( PointerType *) {
     652                visit_children = false;
     653        }
     654
     655        void AutogenerateRoutines::previsit( PointerType *) {
    678656                // ensure that we don't add assignment ops for types defined as part of the pointer
    679         }
    680 
    681         void AutogenerateRoutines::visit( TraitDecl *) {
     657                visit_children = false;
     658        }
     659
     660        void AutogenerateRoutines::previsit( TraitDecl * ) {
    682661                // ensure that we don't add assignment ops for types defined as part of the trait
    683         }
    684 
    685         template< typename StmtClass >
    686         inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
    687                 std::set< std::string > oldStructs = structsDone;
    688                 addVisit( stmt, *this );
    689                 structsDone = oldStructs;
    690         }
    691 
    692         void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
     662                visit_children = false;
     663        }
     664
     665        void AutogenerateRoutines::previsit( FunctionDecl * functionDecl ) {
     666                visit_children = false;
    693667                // record the existence of this function as appropriate
    694668                insert( functionDecl, constructable, InitTweak::isDefaultConstructor );
     
    697671                insert( functionDecl, destructable, InitTweak::isDestructor );
    698672
    699                 maybeAccept( functionDecl->get_functionType(), *this );
     673                maybeAccept( functionDecl->type, *visitor );
    700674                functionNesting += 1;
    701                 maybeAccept( functionDecl->get_statements(), *this );
     675                maybeAccept( functionDecl->statements, *visitor );
    702676                functionNesting -= 1;
    703677        }
    704678
    705         void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
    706                 constructable.beginScope();
    707                 assignable.beginScope();
    708                 copyable.beginScope();
    709                 destructable.beginScope();
    710                 visitStatement( compoundStmt );
    711                 constructable.endScope();
    712                 assignable.endScope();
    713                 copyable.endScope();
    714                 destructable.endScope();
    715         }
    716 
    717         void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
    718                 visitStatement( switchStmt );
     679        void AutogenerateRoutines::previsit( CompoundStmt * ) {
     680                GuardScope( constructable );
     681                GuardScope( assignable );
     682                GuardScope( copyable );
     683                GuardScope( destructable );
     684                GuardScope( structsDone );
    719685        }
    720686
     
    734700        }
    735701
    736         Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) {
    737                 tupleType = strict_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );
     702        void AutogenTupleRoutines::postvisit( TupleType * tupleType ) {
    738703                std::string mangleName = SymTab::Mangler::mangleType( tupleType );
    739                 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;
     704                if ( seenTuples.find( mangleName ) != seenTuples.end() ) return;
    740705                seenTuples.insert( mangleName );
    741706
     
    785750                makeTupleFunctionBody( dtorDecl );
    786751
    787                 addDeclaration( ctorDecl );
    788                 addDeclaration( copyCtorDecl );
    789                 addDeclaration( dtorDecl );
    790                 addDeclaration( assignDecl ); // assignment should come last since it uses copy constructor in return
    791 
    792                 return tupleType;
    793         }
    794 
    795         DeclarationWithType * AutogenTupleRoutines::mutate( FunctionDecl *functionDecl ) {
    796                 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
     752                declsToAddBefore.push_back( ctorDecl );
     753                declsToAddBefore.push_back( copyCtorDecl );
     754                declsToAddBefore.push_back( dtorDecl );
     755                declsToAddBefore.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
     756        }
     757
     758        void AutogenTupleRoutines::previsit( FunctionDecl *functionDecl ) {
     759                visit_children = false;
     760                maybeAccept( functionDecl->type, *visitor );
    797761                functionNesting += 1;
    798                 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     762                maybeAccept( functionDecl->statements, *visitor );
    799763                functionNesting -= 1;
    800                 return functionDecl;
    801         }
    802 
    803         CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) {
    804                 seenTuples.beginScope();
    805                 compoundStmt = strict_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );
    806                 seenTuples.endScope();
    807                 return compoundStmt;
     764        }
     765
     766        void AutogenTupleRoutines::previsit( CompoundStmt * ) {
     767                GuardScope( seenTuples );
    808768        }
    809769} // SymTab
  • src/SymTab/FixFunction.cc

    r201aeb9 rd67cdb7  
    2727
    2828        DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
     29                // can't delete function type because it may contain assertions, so transfer ownership to new object
    2930                ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() );
    3031                functionDecl->get_attributes().clear();
    31                 // can't delete function type because it may contain assertions, but can't transfer ownership without a clone since set_type checks for nullptr
    32                 functionDecl->set_type( functionDecl->get_type()->clone() );
     32                functionDecl->type = nullptr;
    3333                delete functionDecl;
    3434                return pointer;
  • src/SymTab/Indexer.cc

    r201aeb9 rd67cdb7  
    4040
    4141namespace SymTab {
    42         struct NewScope {
    43                 NewScope( SymTab::Indexer & indexer ) : indexer( indexer ) { indexer.enterScope(); }
    44                 ~NewScope() { indexer.leaveScope(); }
    45                 SymTab::Indexer & indexer;
    46         };
    47 
    48         template< typename TreeType, typename VisitorType >
    49         inline void acceptNewScope( TreeType *tree, VisitorType &visitor ) {
    50                 visitor.enterScope();
    51                 maybeAccept( tree, visitor );
    52                 visitor.leaveScope();
    53         }
    54 
    5542        typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable;
    5643        typedef std::unordered_map< std::string, MangleTable > IdTable;
     
    198185        }
    199186
    200         Indexer::Indexer( bool _doDebug ) : tables( 0 ), scope( 0 ), doDebug( _doDebug ) {}
    201 
    202         Indexer::Indexer( const Indexer &that ) : tables( newRef( that.tables ) ), scope( that.scope ), doDebug( that.doDebug ) {}
    203 
    204         Indexer::Indexer( Indexer &&that ) : tables( that.tables ), scope( that.scope ), doDebug( that.doDebug ) {
     187        Indexer::Indexer() : tables( 0 ), scope( 0 ) {}
     188
     189        Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) {}
     190
     191        Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) {
    205192                that.tables = 0;
    206193        }
  • src/SymTab/Indexer.h

    r201aeb9 rd67cdb7  
    2626        class Indexer {
    2727          public:
    28                 explicit Indexer( bool useDebug = false );
     28                explicit Indexer();
    2929
    3030                Indexer( const Indexer &that );
     
    7676                void addTrait( TraitDecl *decl );
    7777
     78                bool doDebug = false; ///< Display debugging trace?
    7879          private:
    7980                struct Impl;
     
    8182                Impl *tables;         ///< Copy-on-write instance of table data structure
    8283                unsigned long scope;  ///< Scope index of this pointer
    83                 bool doDebug;         ///< Display debugging trace?
    8484
    8585                /// Takes a new ref to a table (returns null if null)
  • src/SymTab/Mangler.cc

    r201aeb9 rd67cdb7  
    3131
    3232namespace SymTab {
    33         std::string Mangler::mangleType( Type *ty ) {
     33        std::string Mangler::mangleType( Type * ty ) {
    3434                Mangler mangler( false, true );
    3535                maybeAccept( ty, mangler );
     
    4848        }
    4949
    50         void Mangler::mangleDecl( DeclarationWithType *declaration ) {
     50        void Mangler::mangleDecl( DeclarationWithType * declaration ) {
    5151                bool wasTopLevel = isTopLevel;
    5252                if ( isTopLevel ) {
     
    7979        }
    8080
    81         void Mangler::visit( ObjectDecl *declaration ) {
     81        void Mangler::visit( ObjectDecl * declaration ) {
    8282                mangleDecl( declaration );
    8383        }
    8484
    85         void Mangler::visit( FunctionDecl *declaration ) {
     85        void Mangler::visit( FunctionDecl * declaration ) {
    8686                mangleDecl( declaration );
    8787        }
    8888
    89         void Mangler::visit( VoidType *voidType ) {
     89        void Mangler::visit( VoidType * voidType ) {
    9090                printQualifiers( voidType );
    9191                mangleName << "v";
    9292        }
    9393
    94         void Mangler::visit( BasicType *basicType ) {
     94        void Mangler::visit( BasicType * basicType ) {
    9595                static const char *btLetter[] = {
    9696                        "b",    // Bool
     
    123123        }
    124124
    125         void Mangler::visit( PointerType *pointerType ) {
     125        void Mangler::visit( PointerType * pointerType ) {
    126126                printQualifiers( pointerType );
    127127                mangleName << "P";
     
    129129        }
    130130
    131         void Mangler::visit( ArrayType *arrayType ) {
     131        void Mangler::visit( ArrayType * arrayType ) {
    132132                // TODO: encode dimension
    133133                printQualifiers( arrayType );
     
    136136        }
    137137
    138         void Mangler::visit( ReferenceType *refType ) {
     138        void Mangler::visit( ReferenceType * refType ) {
    139139                printQualifiers( refType );
    140140                mangleName << "R";
     
    151151        }
    152152
    153         void Mangler::visit( FunctionType *functionType ) {
     153        void Mangler::visit( FunctionType * functionType ) {
    154154                printQualifiers( functionType );
    155155                mangleName << "F";
     
    162162        }
    163163
    164         void Mangler::mangleRef( ReferenceToType *refType, std::string prefix ) {
     164        void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
    165165                printQualifiers( refType );
    166166
     
    168168        }
    169169
    170         void Mangler::mangleGenericRef( ReferenceToType *refType, std::string prefix ) {
     170        void Mangler::mangleGenericRef( ReferenceToType * refType, std::string prefix ) {
    171171                printQualifiers( refType );
    172172
     
    191191        }
    192192
    193         void Mangler::visit( StructInstType *aggregateUseType ) {
     193        void Mangler::visit( StructInstType * aggregateUseType ) {
    194194                if ( typeMode ) mangleGenericRef( aggregateUseType, "s" );
    195195                else mangleRef( aggregateUseType, "s" );
    196196        }
    197197
    198         void Mangler::visit( UnionInstType *aggregateUseType ) {
     198        void Mangler::visit( UnionInstType * aggregateUseType ) {
    199199                if ( typeMode ) mangleGenericRef( aggregateUseType, "u" );
    200200                else mangleRef( aggregateUseType, "u" );
    201201        }
    202202
    203         void Mangler::visit( EnumInstType *aggregateUseType ) {
     203        void Mangler::visit( EnumInstType * aggregateUseType ) {
    204204                mangleRef( aggregateUseType, "e" );
    205205        }
    206206
    207         void Mangler::visit( TypeInstType *typeInst ) {
     207        void Mangler::visit( TypeInstType * typeInst ) {
    208208                VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
    209209                if ( varNum == varNums.end() ) {
     
    233233        }
    234234
    235         void Mangler::visit( TupleType *tupleType ) {
     235        void Mangler::visit( TupleType * tupleType ) {
    236236                printQualifiers( tupleType );
    237237                mangleName << "T";
    238                 acceptAll( tupleType->get_types(), *this );
     238                acceptAll( tupleType->types, *this );
    239239                mangleName << "_";
    240240        }
    241241
    242         void Mangler::visit( VarArgsType *varArgsType ) {
     242        void Mangler::visit( VarArgsType * varArgsType ) {
    243243                printQualifiers( varArgsType );
    244244                mangleName << "VARGS";
    245245        }
    246246
    247         void Mangler::visit( __attribute__((unused)) ZeroType *zeroType ) {
     247        void Mangler::visit( ZeroType * ) {
    248248                mangleName << "Z";
    249249        }
    250250
    251         void Mangler::visit( __attribute__((unused)) OneType *oneType ) {
     251        void Mangler::visit( OneType * ) {
    252252                mangleName << "O";
    253253        }
    254254
    255         void Mangler::visit( TypeDecl *decl ) {
     255        void Mangler::visit( TypeDecl * decl ) {
    256256                static const char *typePrefix[] = { "BT", "BD", "BF" };
    257                 mangleName << typePrefix[ decl->get_kind() ] << ( decl->get_name().length() + 1 ) << decl->get_name();
     257                mangleName << typePrefix[ decl->get_kind() ] << ( decl->name.length() + 1 ) << decl->name;
    258258        }
    259259
     
    264264        }
    265265
    266         void Mangler::printQualifiers( Type *type ) {
     266        void Mangler::printQualifiers( Type * type ) {
    267267                // skip if not including qualifiers
    268268                if ( typeMode ) return;
     
    272272                        int tcount = 0, dcount = 0, fcount = 0, vcount = 0;
    273273                        mangleName << "A";
    274                         for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
     274                        for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    275275                                switch ( (*i)->get_kind() ) {
    276276                                  case TypeDecl::Any:
     
    289289                                        assert( false );
    290290                                } // switch
    291                                 varNums[ (*i )->get_name() ] = std::pair< int, int >( nextVarNum++, (int )(*i )->get_kind() );
    292                                 for ( std::list< DeclarationWithType* >::iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
     291                                varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() );
     292                                for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
    293293                                        Mangler sub_mangler( mangleOverridable, typeMode );
    294294                                        sub_mangler.nextVarNum = nextVarNum;
     
    309309                        mangleName << "V";
    310310                } // if
     311                if ( type->get_mutex() ) {
     312                        mangleName << "M";
     313                } // if
    311314                // Removed due to restrict not affecting function compatibility in GCC
    312315//              if ( type->get_isRestrict() ) {
     
    314317//              } // if
    315318                if ( type->get_lvalue() ) {
     319                        // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
    316320                        mangleName << "L";
    317                 } // if
     321                }
    318322                if ( type->get_atomic() ) {
    319323                        mangleName << "A";
  • src/SymTab/Validate.cc

    r201aeb9 rd67cdb7  
    5656#include "FixFunction.h"               // for FixFunction
    5757#include "Indexer.h"                   // for Indexer
     58#include "InitTweak/GenInit.h"         // for fixReturnStatements
    5859#include "InitTweak/InitTweak.h"       // for isCtorDtorAssign
    5960#include "Parser/LinkageSpec.h"        // for C
     
    150151        /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
    151152        struct ForallPointerDecay final {
    152                 void previsit( ObjectDecl *object );
    153                 void previsit( FunctionDecl *func );
     153                void previsit( ObjectDecl * object );
     154                void previsit( FunctionDecl * func );
    154155        };
    155156
     
    579580
    580581        /// Fix up assertions - flattens assertion lists, removing all trait instances
    581         void forallFixer( Type * func ) {
    582                 for ( TypeDecl * type : func->get_forall() ) {
     582        void forallFixer( std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) {
     583                for ( TypeDecl * type : forall ) {
    583584                        std::list< DeclarationWithType * > asserts;
    584585                        asserts.splice( asserts.end(), type->assertions );
     
    599600                                assertion = assertion->acceptMutator( fixer );
    600601                                if ( fixer.get_isVoid() ) {
    601                                         throw SemanticError( "invalid type void in assertion of function ", func );
     602                                        throw SemanticError( "invalid type void in assertion of function ", node );
    602603                                } // if
    603604                        } // for
     
    607608
    608609        void ForallPointerDecay::previsit( ObjectDecl *object ) {
    609                 forallFixer( object->get_type() );
    610                 if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) {
    611                         forallFixer( pointer->get_base() );
     610                forallFixer( object->type->forall, object );
     611                if ( PointerType *pointer = dynamic_cast< PointerType * >( object->type ) ) {
     612                        forallFixer( pointer->base->forall, object );
    612613                } // if
    613614                object->fixUniqueId();
     
    615616
    616617        void ForallPointerDecay::previsit( FunctionDecl *func ) {
    617                 forallFixer( func->get_type() );
     618                forallFixer( func->type->forall, func );
    618619                func->fixUniqueId();
    619620        }
  • src/SynTree/BaseSyntaxNode.h

    r201aeb9 rd67cdb7  
    2626
    2727        virtual void accept( Visitor & v ) = 0;
    28   virtual void print( std::ostream & os, int indent = 0 ) const = 0;
     28        virtual void print( std::ostream & os, int indent = 0 ) const = 0;
    2929};
     30
     31std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node );
    3032
    3133// Local Variables: //
  • src/SynTree/CompoundStmt.cc

    r201aeb9 rd67cdb7  
    2929
    3030CompoundStmt::CompoundStmt( std::list<Label> labels ) : Statement( labels ) {
     31}
     32
     33CompoundStmt::CompoundStmt( std::list<Statement *> stmts ) : Statement( noLabels ), kids( stmts ) {
    3134}
    3235
  • src/SynTree/Constant.cc

    r201aeb9 rd67cdb7  
    3232Constant Constant::from_bool( bool b ) {
    3333        return Constant( new BasicType( Type::Qualifiers(), BasicType::Bool ), b ? "1" : "0" , (unsigned long long int)b );
     34}
     35
     36Constant Constant::from_char( char c ) {
     37        return Constant( new BasicType( Type::Qualifiers(), BasicType::Char ), std::to_string( c ), (unsigned long long int)c );
    3438}
    3539
  • src/SynTree/Constant.h

    r201aeb9 rd67cdb7  
    4040        /// generates a boolean constant of the given bool
    4141        static Constant from_bool( bool b );
     42        /// generates a char constant of the given char
     43        static Constant from_char( char c );
    4244        /// generates an integer constant of the given int
    4345        static Constant from_int( int i );
  • src/SynTree/Declaration.cc

    r201aeb9 rd67cdb7  
    5959}
    6060
    61 std::ostream & operator<<( std::ostream & out, const Declaration * decl ) {
    62         if ( decl ){
    63                 decl->print( out );
    64         } else {
    65                 out << "nullptr";
    66         }
    67         return out;
    68 }
    69 
    7061
    7162AsmDecl::AsmDecl( AsmStmt *stmt ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), stmt( stmt ) {
  • src/SynTree/Declaration.h

    r201aeb9 rd67cdb7  
    6262        void fixUniqueId( void );
    6363        virtual Declaration *clone() const = 0;
    64         virtual void accept( Visitor &v ) = 0;
     64        virtual void accept( Visitor &v ) override = 0;
    6565        virtual Declaration *acceptMutator( Mutator &m ) = 0;
    66         virtual void print( std::ostream &os, int indent = 0 ) const = 0;
     66        virtual void print( std::ostream &os, int indent = 0 ) const override = 0;
    6767        virtual void printShort( std::ostream &os, int indent = 0 ) const = 0;
    6868
     
    106106        //void set_functionSpecifiers( Type::FuncSpecifiers newValue ) { fs = newValue; }
    107107
    108         virtual DeclarationWithType *clone() const = 0;
    109         virtual DeclarationWithType *acceptMutator( Mutator &m ) = 0;
     108        virtual DeclarationWithType *clone() const override = 0;
     109        virtual DeclarationWithType *acceptMutator( Mutator &m )  override = 0;
    110110
    111111        virtual Type * get_type() const = 0;
     
    128128        virtual ~ObjectDecl();
    129129
    130         virtual Type * get_type() const { return type; }
    131         virtual void set_type(Type *newType) { type = newType; }
     130        virtual Type * get_type() const override { return type; }
     131        virtual void set_type(Type *newType) override { type = newType; }
    132132
    133133        Initializer *get_init() const { return init; }
     
    139139        static ObjectDecl * newObject( const std::string & name, Type * type, Initializer * init );
    140140
    141         virtual ObjectDecl *clone() const { return new ObjectDecl( *this ); }
    142         virtual void accept( Visitor &v ) { v.visit( this ); }
    143         virtual DeclarationWithType *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    144         virtual void print( std::ostream &os, int indent = 0 ) const;
    145         virtual void printShort( std::ostream &os, int indent = 0 ) const;
     141        virtual ObjectDecl *clone() const override { return new ObjectDecl( *this ); }
     142        virtual void accept( Visitor &v ) override { v.visit( this ); }
     143        virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     144        virtual void print( std::ostream &os, int indent = 0 ) const override;
     145        virtual void printShort( std::ostream &os, int indent = 0 ) const override;
    146146};
    147147
     
    157157        virtual ~FunctionDecl();
    158158
    159         Type * get_type() const { return type; }
    160         virtual void set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
     159        virtual Type * get_type() const override { return type; }
     160        virtual void set_type(Type * t) override { type = strict_dynamic_cast< FunctionType* >( t ); }
    161161
    162162        FunctionType * get_functionType() const { return type; }
     
    165165        void set_statements( CompoundStmt *newValue ) { statements = newValue; }
    166166
    167         virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
    168         virtual void accept( Visitor &v ) { v.visit( this ); }
    169         virtual DeclarationWithType *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    170         virtual void print( std::ostream &os, int indent = 0 ) const;
    171         virtual void printShort( std::ostream &os, int indent = 0 ) const;
     167        virtual FunctionDecl *clone() const override { return new FunctionDecl( *this ); }
     168        virtual void accept( Visitor &v ) override { v.visit( this ); }
     169        virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     170        virtual void print( std::ostream &os, int indent = 0 ) const override;
     171        virtual void printShort( std::ostream &os, int indent = 0 ) const override;
    172172};
    173173
     
    190190        virtual std::string typeString() const = 0;
    191191
    192         virtual NamedTypeDecl *clone() const = 0;
    193         virtual void print( std::ostream &os, int indent = 0 ) const;
    194         virtual void printShort( std::ostream &os, int indent = 0 ) const;
     192        virtual NamedTypeDecl *clone() const override = 0;
     193        virtual void print( std::ostream &os, int indent = 0 ) const override;
     194        virtual void printShort( std::ostream &os, int indent = 0 ) const override;
    195195};
    196196
     
    227227        TypeDecl * set_sized( bool newValue ) { sized = newValue; return this; }
    228228
    229         virtual std::string typeString() const;
     229        virtual std::string typeString() const override;
    230230        virtual std::string genTypeString() const;
    231231
    232         virtual TypeDecl *clone() const { return new TypeDecl( *this ); }
    233         virtual void accept( Visitor &v ) { v.visit( this ); }
    234         virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    235         virtual void print( std::ostream &os, int indent = 0 ) const;
     232        virtual TypeDecl *clone() const override { return new TypeDecl( *this ); }
     233        virtual void accept( Visitor &v ) override { v.visit( this ); }
     234        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     235        virtual void print( std::ostream &os, int indent = 0 ) const override;
    236236
    237237  private:
     
    245245        TypedefDecl( const TypedefDecl &other ) : Parent( other ) {}
    246246
    247         virtual std::string typeString() const;
    248 
    249         virtual TypedefDecl *clone() const { return new TypedefDecl( *this ); }
    250         virtual void accept( Visitor &v ) { v.visit( this ); }
    251         virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); }
     247        virtual std::string typeString() const override;
     248
     249        virtual TypedefDecl *clone() const override { return new TypedefDecl( *this ); }
     250        virtual void accept( Visitor &v ) override { v.visit( this ); }
     251        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    252252  private:
    253253};
     
    274274        AggregateDecl * set_body( bool body ) { AggregateDecl::body = body; return this; }
    275275
    276         virtual void print( std::ostream &os, int indent = 0 ) const;
    277         virtual void printShort( std::ostream &os, int indent = 0 ) const;
     276        virtual void print( std::ostream &os, int indent = 0 ) const override;
     277        virtual void printShort( std::ostream &os, int indent = 0 ) const override;
    278278  protected:
    279279        virtual std::string typeString() const = 0;
     
    290290        bool is_thread() { return kind == DeclarationNode::Thread; }
    291291
    292         virtual StructDecl *clone() const { return new StructDecl( *this ); }
    293         virtual void accept( Visitor &v ) { v.visit( this ); }
    294         virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); }
     292        virtual StructDecl *clone() const override { return new StructDecl( *this ); }
     293        virtual void accept( Visitor &v ) override { v.visit( this ); }
     294        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
    295295  private:
    296296        DeclarationNode::Aggregate kind;
    297         virtual std::string typeString() const;
     297        virtual std::string typeString() const override;
    298298};
    299299
     
    304304        UnionDecl( const UnionDecl &other ) : Parent( other ) {}
    305305
    306         virtual UnionDecl *clone() const { return new UnionDecl( *this ); }
    307         virtual void accept( Visitor &v ) { v.visit( this ); }
    308         virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    309   private:
    310         virtual std::string typeString() const;
     306        virtual UnionDecl *clone() const override { return new UnionDecl( *this ); }
     307        virtual void accept( Visitor &v ) override { v.visit( this ); }
     308        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     309  private:
     310        virtual std::string typeString() const override;
    311311};
    312312
     
    317317        EnumDecl( const EnumDecl &other ) : Parent( other ) {}
    318318
    319         virtual EnumDecl *clone() const { return new EnumDecl( *this ); }
    320         virtual void accept( Visitor &v ) { v.visit( this ); }
    321         virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    322   private:
    323         virtual std::string typeString() const;
     319        virtual EnumDecl *clone() const override { return new EnumDecl( *this ); }
     320        virtual void accept( Visitor &v ) override { v.visit( this ); }
     321        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     322  private:
     323        virtual std::string typeString() const override;
    324324};
    325325
     
    332332        TraitDecl( const TraitDecl &other ) : Parent( other ) {}
    333333
    334         virtual TraitDecl *clone() const { return new TraitDecl( *this ); }
    335         virtual void accept( Visitor &v ) { v.visit( this ); }
    336         virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    337   private:
    338         virtual std::string typeString() const;
     334        virtual TraitDecl *clone() const override { return new TraitDecl( *this ); }
     335        virtual void accept( Visitor &v ) override { v.visit( this ); }
     336        virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     337  private:
     338        virtual std::string typeString() const override;
    339339};
    340340
     
    350350        void set_stmt( AsmStmt *newValue ) { stmt = newValue; }
    351351
    352         virtual AsmDecl *clone() const { return new AsmDecl( *this ); }
    353         virtual void accept( Visitor &v ) { v.visit( this ); }
    354         virtual AsmDecl *acceptMutator( Mutator &m ) { return m.mutate( this ); }
    355         virtual void print( std::ostream &os, int indent = 0 ) const;
    356         virtual void printShort( std::ostream &os, int indent = 0 ) const;
    357 };
    358 
    359 std::ostream & operator<<( std::ostream & out, const Declaration * decl );
     352        virtual AsmDecl *clone() const override { return new AsmDecl( *this ); }
     353        virtual void accept( Visitor &v ) override { v.visit( this ); }
     354        virtual AsmDecl *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     355        virtual void print( std::ostream &os, int indent = 0 ) const override;
     356        virtual void printShort( std::ostream &os, int indent = 0 ) const override;
     357};
     358
    360359std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data );
    361360
  • src/SynTree/Expression.cc

    r201aeb9 rd67cdb7  
    741741}
    742742
    743 
    744 std::ostream & operator<<( std::ostream & out, const Expression * expr ) {
    745         if ( expr ) {
    746                 expr->print( out );
    747         } else {
    748                 out << "nullptr";
    749         }
    750         return out;
    751 }
    752 
    753743// Local Variables: //
    754744// tab-width: 4 //
  • src/SynTree/Expression.h

    r201aeb9 rd67cdb7  
    821821};
    822822
    823 
    824 std::ostream & operator<<( std::ostream & out, const Expression * expr );
    825 
    826823// Local Variables: //
    827824// tab-width: 4 //
  • src/SynTree/Initializer.cc

    r201aeb9 rd67cdb7  
    137137}
    138138
    139 std::ostream & operator<<( std::ostream & out, const Initializer * init ) {
    140         if ( init ) {
    141                 init->print( out );
    142         } else {
    143                 out << "nullptr";
    144         }
    145         return out;
    146 }
    147 
    148 std::ostream & operator<<( std::ostream & out, const Designation * des ) {
    149         if ( des ) {
    150                 des->print( out );
    151         } else {
    152                 out << "nullptr";
    153         }
    154         return out;
    155 }
    156 
    157139// Local Variables: //
    158140// tab-width: 4 //
  • src/SynTree/Initializer.h

    r201aeb9 rd67cdb7  
    3838
    3939        virtual Designation * clone() const { return new Designation( *this ); };
    40         virtual void accept( Visitor &v ) { v.visit( this ); }