Changeset d67cdb7
- Timestamp:
- Sep 26, 2017, 11:27:38 PM (7 years ago)
- 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
- Files:
-
- 11 added
- 6 deleted
- 70 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/proposals/concurrency/Makefile
r201aeb9 rd67cdb7 17 17 text/concurrency \ 18 18 text/parallelism \ 19 text/together \ 20 text/future \ 19 21 } 20 22 -
doc/proposals/concurrency/annex/glossary.tex
r201aeb9 rd67cdb7 101 101 \newacronym{api}{API}{Application Program Interface} 102 102 \newacronym{raii}{RAII}{Ressource Acquisition Is Initialization} 103 \newacronym{numa}{NUMA}{Non-Uniform Memory Access} -
doc/proposals/concurrency/text/cforall.tex
r201aeb9 rd67cdb7 15 15 int x, *p1 = &x, **p2 = &p1, ***p3 = &p2, 16 16 &r1 = x, &&r2 = r1, &&&r3 = r2; 17 ***p3 = 3; 18 r3 = 3; 19 **p3 = ...; 20 &r3 = ...; 21 *p3 = ...; 22 &&r3 = ...; 23 &&&r3 = p3; 24 int y, z, & ar[3] = { x, y, z }; 25 &ar[1] = &z; 26 typeof( ar[1] ) p; 27 typeof( &ar[1] ) q; 28 sizeof( ar[1] ) == sizeof( int ); 29 sizeof( &ar[1] ) == sizeof( int *); 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 30 30 \end{cfacode} 31 31 The 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. … … 36 36 \begin{cfacode} 37 37 // selection based on type and number of parameters 38 void f( void ); 39 void f( char ); 40 void f( int, double ); 41 f(); 42 f( 'a' ); 43 f( 3, 5.2 ); 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) 44 44 45 45 // selection based on type and number of returns 46 char f( int ); 47 double f( int ); 48 [ int, double ] f( int ); 49 char c = f( 3 ); 50 double d = f( 4 ); 51 [ int, double ] t = f( 5 ); 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) 52 52 \end{cfacode} 53 53 This 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. … … 56 56 Overloading 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 : 57 57 \begin{cfacode} 58 int ++?( int op ); 59 int ?++( int op ); 60 int ?+?( int op1, int op2 ); 61 int ?<=?( int op1, int op2 ); 62 int ?=?( int & op1, int op2 ); 63 int ?+=?( int & op1, int op2 ); 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 64 64 65 65 struct S { int i, j; }; 66 S ?+?( S op1, S op2 ) { 66 S ?+?( S op1, S op2 ) { // add two structures 67 67 return (S){ op1.i + op2.i, op1.j + op2.j }; 68 68 } 69 69 S s1 = { 1, 2 }, s2 = { 2, 3 }, s3; 70 s3 = s1 + s2; 70 s3 = s1 + s2; // compute sum: s3 == { 2, 5 } 71 71 \end{cfacode} 72 72 … … 74 74 75 75 \section{Constructors/Destructors} 76 \CFA uses the following syntax for constructors and destructors :76 Object 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 : 77 77 \begin{cfacode} 78 78 struct S { … … 80 80 int * ia; 81 81 }; 82 void ?{}( S & s, int asize ) with s { 83 size = asize; 82 void ?{}( S & s, int asize ) with s { // constructor operator 83 size = asize; // initialize fields 84 84 ia = calloc( size, sizeof( S ) ); 85 85 } 86 void ^?{}( S & s ) with s { 87 free( ia ); 86 void ^?{}( S & s ) with s { // destructor operator 87 free( ia ); // de-initialization fields 88 88 } 89 89 int main() { 90 S x = { 10 }, y = { 100 }; 91 ... 92 ^x{}; ^y{}; 93 x{ 20 }; y{ 200 }; 94 ... 95 } 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 ) 96 96 \end{cfacode} 97 97 The 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 69 69 int f5(graph(monitor*) & mutex m); 70 70 \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: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 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: 72 72 73 73 \begin{cfacode} … … 608 608 % ====================================================================== 609 609 % ====================================================================== 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.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 \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. 611 611 612 612 The 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. … … 832 832 To 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. 833 833 834 % ====================================================================== 835 % ====================================================================== 836 \section{Other concurrency tools} 837 % ====================================================================== 838 % ====================================================================== 839 % \TODO 834 835 \subsection{Internals} 836 The 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 3 3 % ====================================================================== 4 4 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 \CFA5 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 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 6 6 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 requiredifferent tools~\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization, while parallelism tools are about performance, cost and resource utilization.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 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 11 11 \section{Paradigm} 12 12 \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 expensive s 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.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 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. 14 14 15 15 Examples of languages that support \glspl{uthread} are Erlang~\cite{Erlang} and \uC~\cite{uC++book}. 16 16 17 17 \subsection{Fibers : user-level threads without preemption} 18 A popular varient of \glspl{uthread} is what is often ref fered 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 controversialand the ease of implementation, while true, is a weak argument in the context of language design. Therefore this proposal largely ignore fibers.18 A 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. 19 19 20 20 An example of a language that uses fibers is Go~\cite{Go} 21 21 22 22 \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.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, 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. 24 24 25 25 The gold standard of this implementation is Intel's TBB library~\cite{TBB}. 26 26 27 27 \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.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 (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. 29 29 30 \newpage31 30 \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} 33 33 34 34 35 \subsubsection{Future Work: Machine setup}\label{machine} 36 While 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 35 38 \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? 39 Given 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 1 1 % requires tex packages: texlive-base texlive-latex-base tex-common texlive-humanities texlive-latex-extra texlive-fonts-recommended 2 2 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-^ 9 9 % math escape $...$ (dollar symbol) 10 10 … … 27 27 \usepackage{multicol} 28 28 \usepackage[acronym]{glossaries} 29 \usepackage{varioref} 29 \usepackage{varioref} 30 30 \usepackage{listings} % format program code 31 31 \usepackage[flushmargin]{footmisc} % support label/reference in footnote … … 103 103 \input{parallelism} 104 104 105 \chapter{Putting it all together} 105 \input{together} 106 107 \input{future} 106 108 107 109 \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}112 110 113 111 \section*{Acknowledgements} -
doc/proposals/concurrency/version
r201aeb9 rd67cdb7 1 0. 9.1801 0.10.2 -
src/CodeGen/CodeGenerator.cc
r201aeb9 rd67cdb7 443 443 void CodeGenerator::postvisit( UntypedExpr * untypedExpr ) { 444 444 extension( untypedExpr ); 445 if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr-> get_function()) ) {445 if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->function ) ) { 446 446 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(); 449 449 switch ( opInfo.type ) { 450 450 case OT_INDEX: 451 assert( untypedExpr-> get_args().size() == 2 );451 assert( untypedExpr->args.size() == 2 ); 452 452 (*arg++)->accept( *visitor ); 453 453 output << "["; … … 461 461 case OT_CTOR: 462 462 case OT_DTOR: 463 if ( untypedExpr-> get_args().size() == 1 ) {463 if ( untypedExpr->args.size() == 1 ) { 464 464 // the expression fed into a single parameter constructor or destructor may contain side 465 465 // effects, so must still output this expression … … 480 480 (*arg++)->accept( *visitor ); 481 481 output << opInfo.symbol << "{ "; 482 genCommaList( arg, untypedExpr-> get_args().end() );482 genCommaList( arg, untypedExpr->args.end() ); 483 483 output << "}) /* " << opInfo.inputName << " */"; 484 484 } // if … … 488 488 case OT_PREFIXASSIGN: 489 489 case OT_LABELADDRESS: 490 assert( untypedExpr-> get_args().size() == 1 );490 assert( untypedExpr->args.size() == 1 ); 491 491 output << "("; 492 492 output << opInfo.symbol; … … 497 497 case OT_POSTFIX: 498 498 case OT_POSTFIXASSIGN: 499 assert( untypedExpr-> get_args().size() == 1 );499 assert( untypedExpr->args.size() == 1 ); 500 500 (*arg)->accept( *visitor ); 501 501 output << opInfo.symbol; … … 504 504 case OT_INFIX: 505 505 case OT_INFIXASSIGN: 506 assert( untypedExpr-> get_args().size() == 2 );506 assert( untypedExpr->args.size() == 2 ); 507 507 output << "("; 508 508 (*arg++)->accept( *visitor ); … … 517 517 } // switch 518 518 } 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 << ")"; 530 524 } // if 531 525 } else { 532 untypedExpr-> get_function()->accept( *visitor );526 untypedExpr->function->accept( *visitor ); 533 527 output << "("; 534 genCommaList( untypedExpr-> get_args().begin(), untypedExpr->get_args().end() );528 genCommaList( untypedExpr->args.begin(), untypedExpr->args.end() ); 535 529 output << ")"; 536 530 } // if … … 538 532 539 533 void CodeGenerator::postvisit( RangeExpr * rangeExpr ) { 540 rangeExpr-> get_low()->accept( *visitor );534 rangeExpr->low->accept( *visitor ); 541 535 output << " ... "; 542 rangeExpr-> get_high()->accept( *visitor );536 rangeExpr->high->accept( *visitor ); 543 537 } 544 538 … … 885 879 886 880 void CodeGenerator::postvisit( CaseStmt * caseStmt ) { 881 updateLocation( caseStmt ); 882 output << indent; 887 883 if ( caseStmt->isDefault()) { 888 884 output << "default"; … … 1026 1022 } // namespace CodeGen 1027 1023 1024 std::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 1028 1033 // Local Variables: // 1029 1034 // tab-width: 4 // -
src/Concurrency/Keywords.cc
r201aeb9 rd67cdb7 528 528 DeclarationWithType * param = decl->get_functionType()->get_parameters().front(); 529 529 auto type = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) ); 530 // if( type ) std::cerr << "FRED2" << std::endl;531 530 if( type && type->get_baseStruct()->is_thread() ) { 532 531 addStartStatement( decl, param ); -
src/Concurrency/Waitfor.cc
r201aeb9 rd67cdb7 27 27 #include "InitTweak/InitTweak.h" // for getPointerBase 28 28 #include "Parser/LinkageSpec.h" // for Cforall 29 #include " SymTab/AddVisit.h" // for acceptAndAdd29 #include "ResolvExpr/Resolver.h" // for findVoidExpression 30 30 #include "SynTree/Constant.h" // for Constant 31 31 #include "SynTree/Declaration.h" // for StructDecl, FunctionDecl, ObjectDecl … … 112 112 //============================================================================================= 113 113 114 class GenerateWaitForPass final : public With StmtsToAdd{114 class GenerateWaitForPass final : public WithIndexer { 115 115 public: 116 116 … … 126 126 127 127 ObjectDecl * declare( unsigned long count, CompoundStmt * stmt ); 128 ObjectDecl * declareFlag( CompoundStmt * stmt ); 129 Statement * makeSetter( ObjectDecl * flag ); 128 130 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 ); 133 135 134 136 static void implement( std::list< Declaration * > & translationUnit ) { … … 140 142 private: 141 143 FunctionDecl * decl_waitfor = nullptr; 144 StructDecl * decl_mask = nullptr; 142 145 StructDecl * decl_acceptable = nullptr; 143 146 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;148 147 149 148 static std::unique_ptr< Type > generic_func; 150 149 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; 151 154 UniqueName namer_mon = "__monitors_"s; 152 UniqueName namer_acc = "__acceptables_"s;153 155 UniqueName namer_tim = "__timeout_"s; 154 156 }; … … 167 169 namespace { 168 170 Expression * makeOpIndex( DeclarationWithType * array, unsigned long index ) { 169 return new ApplicationExpr(171 return new UntypedExpr( 170 172 new NameExpr( "?[?]" ), 171 173 { … … 177 179 178 180 Expression * makeOpAssign( Expression * lhs, Expression * rhs ) { 179 return new ApplicationExpr(181 return new UntypedExpr( 180 182 new NameExpr( "?=?" ), 181 183 { lhs, rhs } … … 183 185 } 184 186 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 199 197 ), 200 value 201 ) 202 ); 198 member 199 ), 200 value 201 ) ); 202 203 return new ExprStmt( noLabels, ResolvExpr::findVoidExpression( expr.get(), indexer ) ); 203 204 } 204 205 … … 208 209 return new ConstantExpr( Constant::from_bool( ifnull ) ); 209 210 } 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 } 210 226 }; 211 227 … … 216 232 217 233 void GenerateWaitForPass::premutate( FunctionDecl * decl) { 218 if( decl->name != "__ accept_internal" ) return;234 if( decl->name != "__waitfor_internal" ) return; 219 235 220 236 decl_waitfor = decl; … … 227 243 assert( !decl_acceptable ); 228 244 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; 236 249 } 237 250 else if( decl->name == "monitor_desc" ) { … … 242 255 243 256 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 ); 247 258 248 259 CompoundStmt * stmt = new CompoundStmt( noLabels ); 249 260 250 261 ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt ); 262 ObjectDecl * flag = declareFlag( stmt ); 263 Statement * setter = makeSetter( flag ); 251 264 252 265 int index = 0; 253 266 for( auto & clause : waitfor->clauses ) { 254 init( acceptables, index, clause, s tmt );267 init( acceptables, index, clause, setter, stmt ); 255 268 256 269 index++; … … 262 275 waitfor->orelse .statement, 263 276 waitfor->orelse .condition, 277 setter, 264 278 stmt 265 279 ); 266 280 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 ); 270 292 271 293 return stmt; … … 274 296 ObjectDecl * GenerateWaitForPass::declare( unsigned long count, CompoundStmt * stmt ) 275 297 { 276 ObjectDecl * acceptables = new ObjectDecl(298 ObjectDecl * acceptables = ObjectDecl::newObject( 277 299 namer_acc.newName(), 278 noStorage,279 LinkageSpec::Cforall,280 nullptr,281 300 new ArrayType( 282 301 noQualifiers, … … 294 313 stmt->push_back( new DeclStmt( noLabels, acceptables) ); 295 314 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 296 329 return acceptables; 297 330 } 298 331 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 299 362 ObjectDecl * GenerateWaitForPass::declMon( WaitForStmt::Clause & clause, CompoundStmt * stmt ) { 300 363 301 ObjectDecl * mon = new ObjectDecl(364 ObjectDecl * mon = ObjectDecl::newObject( 302 365 namer_mon.newName(), 303 noStorage,304 LinkageSpec::Cforall,305 nullptr,306 366 new ArrayType( 307 367 noQualifiers, 308 new StructInstType(368 new PointerType( 309 369 noQualifiers, 310 decl_monitor 370 new StructInstType( 371 noQualifiers, 372 decl_monitor 373 ) 311 374 ), 312 375 new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), … … 316 379 new ListInit( 317 380 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 ); 319 398 }) 320 399 ) … … 326 405 } 327 406 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 ) { 329 408 330 409 ObjectDecl * monitors = declMon( clause, stmt ); 331 410 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 ) ); 337 412 338 413 stmt->push_back( new IfStmt( 339 414 noLabels, 340 415 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 }), 342 423 nullptr 343 424 )); … … 353 434 bool has_else, 354 435 Expression *& else_cond, 436 Statement * setter, 355 437 CompoundStmt * stmt 356 438 ) { 357 ObjectDecl * timeout = new ObjectDecl(439 ObjectDecl * timeout = ObjectDecl::newObject( 358 440 namer_tim.newName(), 359 noStorage,360 LinkageSpec::Cforall,361 nullptr,362 441 new BasicType( 363 442 noQualifiers, … … 374 453 stmt->push_back( new IfStmt( 375 454 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 }), 384 466 nullptr 385 467 )); … … 392 474 noLabels, 393 475 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 }), 401 486 nullptr 402 487 )); … … 405 490 } 406 491 492 delete setter; 493 407 494 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 ); 408 618 } 409 619 }; -
src/GenPoly/Box.cc
r201aeb9 rd67cdb7 32 32 #include "Common/UniqueName.h" // for UniqueName 33 33 #include "Common/utility.h" // for toString 34 #include "DeclMutator.h" // for DeclMutator35 34 #include "FindFunction.h" // for findFunction, findAndReplace... 36 35 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_i... … … 39 38 #include "Lvalue.h" // for generalizedLvalue 40 39 #include "Parser/LinkageSpec.h" // for C, Spec, Cforall, Intrinsic 41 #include "PolyMutator.h" // for PolyMutator42 40 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass 43 41 #include "ResolvExpr/typeops.h" // for typesCompatible … … 62 60 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ); 63 61 62 class BoxPass { 63 protected: 64 BoxPass() : scopeTyVars( TypeDecl::Data{} ) {} 65 TyVarMap scopeTyVars; 66 }; 67 64 68 /// Adds layout-generation functions to polymorphic types 65 class LayoutFunctionBuilder final : public DeclMutator{66 unsigned int functionNesting ; // current level of nested functions69 class LayoutFunctionBuilder final : public WithDeclsToAdd, public WithVisitorRef<LayoutFunctionBuilder>, public WithShortCircuiting { 70 unsigned int functionNesting = 0; // current level of nested functions 67 71 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 ); 74 75 }; 75 76 76 77 /// 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 { 78 79 public: 79 80 Pass1(); 80 81 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(); 95 95 private: 96 96 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application … … 129 129 /// * Moves polymorphic returns in function types to pointer-type parameters 130 130 /// * 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 ); 149 141 150 142 private: … … 158 150 /// * Calculates polymorphic offsetof expressions from offset array 159 151 /// * 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 { 161 153 public: 162 154 PolyGenericCalculator(); … … 197 189 ScopedSet< std::string > knownOffsets; ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName 198 190 UniqueName bufNamer; ///< Namer for VLA buffers 199 TyVarMap scopeTyVars;200 191 }; 201 192 202 193 /// 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 { 205 195 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 ); 218 206 }; 219 207 } // anonymous namespace … … 247 235 248 236 void box( std::list< Declaration *>& translationUnit ) { 249 LayoutFunctionBuilderlayoutBuilder;250 Pass 1pass1;251 Pass 2pass2;237 PassVisitor<LayoutFunctionBuilder> layoutBuilder; 238 PassVisitor<Pass1> pass1; 239 PassVisitor<Pass2> pass2; 252 240 PassVisitor<PolyGenericCalculator> polyCalculator; 253 Pass 3pass3;254 255 layoutBuilder.mutateDeclarationList( translationUnit);256 mutate TranslationUnit/*All*/( translationUnit, pass1 );257 mutate TranslationUnit/*All*/( translationUnit, pass2 );241 PassVisitor<Pass3> pass3; 242 243 acceptAll( translationUnit, layoutBuilder ); 244 mutateAll( translationUnit, pass1 ); 245 mutateAll( translationUnit, pass2 ); 258 246 mutateAll( translationUnit, polyCalculator ); 259 mutate TranslationUnit/*All*/( translationUnit, pass3 );247 mutateAll( translationUnit, pass3 ); 260 248 } 261 249 262 250 ////////////////////////////////// LayoutFunctionBuilder //////////////////////////////////////////// 263 251 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 ); 266 255 ++functionNesting; 267 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ));256 maybeAccept( functionDecl->get_statements(), *visitor ); 268 257 --functionNesting; 269 return functionDecl;270 258 } 271 259 … … 356 344 } 357 345 358 Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {346 void LayoutFunctionBuilder::previsit( StructDecl *structDecl ) { 359 347 // 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; 361 350 362 351 // get parameters that can change layout, exiting early if none 363 352 std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() ); 364 if ( otypeParams.empty() ) return structDecl;353 if ( otypeParams.empty() ) return; 365 354 366 355 // build layout function signature … … 413 402 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) ); 414 403 415 addDeclarationAfter( layoutDecl ); 416 return structDecl; 404 declsToAddAfter.push_back( layoutDecl ); 417 405 } 418 406 419 Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {407 void LayoutFunctionBuilder::previsit( UnionDecl *unionDecl ) { 420 408 // 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; 422 411 423 412 // get parameters that can change layout, exiting early if none 424 413 std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() ); 425 if ( otypeParams.empty() ) return unionDecl;414 if ( otypeParams.empty() ) return; 426 415 427 416 // build layout function signature … … 456 445 addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) ); 457 446 458 addDeclarationAfter( layoutDecl ); 459 return unionDecl; 447 declsToAddAfter.push_back( layoutDecl ); 460 448 } 461 449 … … 501 489 Pass1::Pass1() : tempNamer( "_temp" ) {} 502 490 503 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {491 void Pass1::premutate( FunctionDecl *functionDecl ) { 504 492 if ( functionDecl->get_statements() ) { // empty routine body ? 505 493 // 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 ); 510 496 511 497 // process polymorphic return value 512 498 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(); 515 502 516 503 // 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; 520 507 } // if 521 508 } // if 522 509 523 FunctionType *functionType = functionDecl->get_functionType(); 524 makeTyVarMap( functionDecl->get_functionType(), scopeTyVars ); 525 526 std::list< DeclarationWithType *> ¶mList = functionType->get_parameters(); 510 makeTyVarMap( functionType, scopeTyVars ); 511 512 std::list< DeclarationWithType *> ¶mList = functionType->parameters; 527 513 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 ) { 530 516 findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter ); 531 517 } // for … … 542 528 } // if 543 529 } // for 544 545 functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );546 547 scopeTyVars.endScope();548 retval = oldRetval;549 doEndScope();550 530 // std::cerr << "end function: " << functionDecl->get_mangleName() << std::endl; 551 531 } // if 552 return functionDecl; 553 } 554 555 TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) { 532 } 533 534 void Pass1::premutate( TypeDecl *typeDecl ) { 556 535 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 ) { 561 539 // Attempting to find application expressions that were mutated by the copy constructor passes 562 540 // to use an explicit return variable, so that the variable can be reused as a parameter to the … … 574 552 } 575 553 } 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 588 554 } 589 555 … … 659 625 ObjectDecl *Pass1::makeTemporary( Type *type ) { 660 626 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 ) ); 662 628 return newObj; 663 629 } … … 775 741 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 ); 776 742 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 ) ); 778 744 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax? 779 745 assign->get_args().push_back( new VariableExpr( newObj ) ); 780 746 assign->get_args().push_back( arg ); 781 stmtsToAdd .push_back( new ExprStmt( noLabels, assign ) );747 stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) ); 782 748 arg = new AddressExpr( new VariableExpr( newObj ) ); 783 749 } // if … … 961 927 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) ); 962 928 adapter = answer.first; 963 stmtsToAdd .push_back( new DeclStmt( noLabels, newAdapter ) );929 stmtsToAddBefore.push_back( new DeclStmt( noLabels, newAdapter ) ); 964 930 } // if 965 931 assert( adapter != adapters.end() ); … … 1118 1084 } 1119 1085 1120 Expression *Pass1:: mutate( ApplicationExpr *appExpr ) {1086 Expression *Pass1::postmutate( ApplicationExpr *appExpr ) { 1121 1087 // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl; 1122 1088 // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) { … … 1124 1090 // } 1125 1091 // 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() ); 1132 1096 1133 1097 if ( Expression *newExpr = handleIntrinsics( appExpr ) ) { … … 1182 1146 } 1183 1147 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 ) ) { 1187 1151 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(); 1190 1154 delete expr; 1191 return ret ->acceptMutator( *this );1155 return ret; 1192 1156 } // if 1193 1157 } // if 1194 1158 } // 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 ) { 1199 1164 assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() ); 1200 1165 … … 1216 1181 // isPolyType check needs to happen before mutating addrExpr arg, so pull it forward 1217 1182 // out of the if condition. 1218 addrExpr-> set_arg( mutateExpression( addrExpr->get_arg() ));1183 addrExpr->arg = addrExpr->get_arg()->acceptMutator( *visitor ); 1219 1184 // ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment 1220 1185 bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env ); … … 1231 1196 } 1232 1197 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; 1240 1203 } // 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 ); 1246 1208 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 ); 1256 1213 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() { 1265 1217 adapters.beginScope(); 1266 1218 } 1267 1219 1268 void Pass1:: doEndScope() {1220 void Pass1::endScope() { 1269 1221 adapters.endScope(); 1270 1222 } … … 1293 1245 } 1294 1246 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 ) { 1304 1248 FunctionType * ftype = functionDecl->get_functionType(); 1305 1249 if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) { … … 1325 1269 } 1326 1270 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 * ) { 1333 1272 // 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 ) { 1353 1287 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 ); 1367 1292 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 ); 1378 1297 makeTyVarMap( funcType, scopeTyVars ); 1379 1298 … … 1414 1333 // move all assertions into parameter list 1415 1334 for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) { 1416 // *assert = (*assert)->acceptMutator( *this );1417 1335 // assertion parameters may not be used in body, pass along with unused attribute. 1418 1336 (*assert)->get_attributes().push_back( new Attribute( "unused" ) ); … … 1450 1368 } 1451 1369 } 1452 1453 1370 seenTypes.insert( typeName ); 1454 1371 } … … 1458 1375 funcType->get_parameters().splice( last, inferredParams ); 1459 1376 addAdapters( funcType ); 1460 mutateAll( funcType->get_returnVals(), *this );1461 mutateAll( funcType->get_parameters(), *this );1462 1463 scopeTyVars.endScope();1464 return funcType;1465 1377 } 1466 1378 … … 1468 1380 1469 1381 PolyGenericCalculator::PolyGenericCalculator() 1470 : knownLayouts(), knownOffsets(), bufNamer( "_buf" ) , scopeTyVars( TypeDecl::Data{} ){}1382 : knownLayouts(), knownOffsets(), bufNamer( "_buf" ) {} 1471 1383 1472 1384 void PolyGenericCalculator::beginTypeScope( Type *ty ) { … … 1829 1741 1830 1742 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 ); 1833 1745 makeTyVarMap( type, scopeTyVars ); 1834 1835 DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );1836 // ScrubTyVars::scrub( decl, scopeTyVars );1837 1746 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 ); 1853 1759 } 1854 1760 1855 1761 /// 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 ) { 1861 1767 stripGenericMembers( structDecl ); 1862 return structDecl; 1863 } 1864 1865 Declaration *Pass3::mutate( UnionDecl *unionDecl ) { 1768 } 1769 1770 void Pass3::premutate( UnionDecl * unionDecl ) { 1866 1771 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 ) { 1879 1775 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 ); 1885 1780 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 ); 1895 1785 makeTyVarMap( functionType, scopeTyVars ); 1896 1897 Type *ret = Mutator::mutate( functionType );1898 1899 scopeTyVars.endScope();1900 return ret;1901 1786 } 1902 1787 } // anonymous namespace -
src/GenPoly/Specialize.cc
r201aeb9 rd67cdb7 22 22 #include <utility> // for pair 23 23 24 #include "Common/PassVisitor.h" 24 25 #include "Common/SemanticError.h" // for SemanticError 25 26 #include "Common/UniqueName.h" // for UniqueName … … 28 29 #include "InitTweak/InitTweak.h" // for isIntrinsicCallExpr 29 30 #include "Parser/LinkageSpec.h" // for C 30 #include "PolyMutator.h" // for PolyMutator31 31 #include "ResolvExpr/FindOpenVars.h" // for findOpenVars 32 32 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet … … 43 43 44 44 namespace 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 ); 54 49 55 50 void handleExplicitParams( ApplicationExpr *appExpr ); … … 204 199 } 205 200 206 struct EnvTrimmer : public Visitor{201 struct EnvTrimmer { 207 202 TypeSubstitution * env, * newEnv; 208 203 EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){} 209 v irtual voidvisit( TypeDecl * tyDecl ) {204 void previsit( TypeDecl * tyDecl ) { 210 205 // 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 ); 213 208 } 214 209 } … … 219 214 if ( env ) { 220 215 TypeSubstitution * newEnv = new TypeSubstitution(); 221 EnvTrimmertrimmer( env, newEnv );216 PassVisitor<EnvTrimmer> trimmer( env, newEnv ); 222 217 expr->accept( trimmer ); 223 218 return newEnv; … … 277 272 std::string oldParamPrefix = paramPrefix; 278 273 paramPrefix += "p"; 279 // save stmtsToAdd in oldStmts274 // save stmtsToAddBefore in oldStmts 280 275 std::list< Statement* > oldStmts; 281 oldStmts.splice( oldStmts.end(), stmtsToAdd );282 mutate( appExpr );276 oldStmts.splice( oldStmts.end(), stmtsToAddBefore ); 277 appExpr->acceptMutator( *visitor ); 283 278 paramPrefix = oldParamPrefix; 284 279 // 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 ); 288 283 289 284 // add return (or valueless expression) to the thunk 290 285 Statement *appStmt; 291 if ( funType-> get_returnVals().empty() ) {286 if ( funType->returnVals.empty() ) { 292 287 appStmt = new ExprStmt( noLabels, appExpr ); 293 288 } else { 294 289 appStmt = new ReturnStmt( noLabels, appExpr ); 295 290 } // if 296 thunkFunc-> get_statements()->get_kids().push_back( appStmt );291 thunkFunc->statements->kids.push_back( appStmt ); 297 292 298 293 // 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 ) ); 300 295 // return address of thunk function as replacement expression 301 296 return new AddressExpr( new VariableExpr( thunkFunc ) ); … … 304 299 void Specialize::handleExplicitParams( ApplicationExpr *appExpr ) { 305 300 // 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 ); 308 303 assert( function ); 309 304 std::list< DeclarationWithType* >::iterator formal; 310 305 std::list< Expression* >::iterator actual; 311 306 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 ) { 320 312 if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) { 321 313 // create thunks for the inferred parameters … … 331 323 } 332 324 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 ) ); 337 328 return addrExpr; 338 329 } 339 330 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() ) { 343 333 // can't specialize if we don't have a return value 344 334 return castExpr; 345 335 } 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 ) { 348 338 // assume here that the specialization incorporates the cast 349 339 return specialized; … … 353 343 } 354 344 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 parts357 // 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 371 345 void convertSpecializations( std::list< Declaration* >& translationUnit ) { 372 Specializespec;346 PassVisitor<Specialize> spec; 373 347 mutateAll( translationUnit, spec ); 374 348 } -
src/GenPoly/module.mk
r201aeb9 rd67cdb7 6 6 ## file "LICENCE" distributed with Cforall. 7 7 ## 8 ## module.mk -- 8 ## module.mk -- 9 9 ## 10 10 ## Author : Richard C. Bilson … … 17 17 SRC += GenPoly/Box.cc \ 18 18 GenPoly/GenPoly.cc \ 19 GenPoly/PolyMutator.cc \20 19 GenPoly/ScrubTyVars.cc \ 21 20 GenPoly/Lvalue.cc \ … … 23 22 GenPoly/CopyParams.cc \ 24 23 GenPoly/FindFunction.cc \ 25 GenPoly/DeclMutator.cc \26 24 GenPoly/InstantiateGeneric.cc -
src/InitTweak/FixInit.cc
r201aeb9 rd67cdb7 36 36 #include "FixGlobalInit.h" // for fixGlobalInit 37 37 #include "GenInit.h" // for genCtorDtor 38 #include "GenPoly/DeclMutator.h" // for DeclMutator39 38 #include "GenPoly/GenPoly.h" // for getFunctionType 40 #include "GenPoly/PolyMutator.h" // for PolyMutator41 39 #include "InitTweak.h" // for getFunctionName, getCallArg 42 40 #include "Parser/LinkageSpec.h" // for C, Spec, Cforall, isBuiltin … … 46 44 #include "SymTab/Indexer.h" // for Indexer 47 45 #include "SymTab/Mangler.h" // for Mangler 48 #include "SynTree/AddStmtVisitor.h" // for AddStmtVisitor49 46 #include "SynTree/Attribute.h" // for Attribute 50 47 #include "SynTree/Constant.h" // for Constant … … 58 55 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution, operator<< 59 56 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 60 #include "Tuples/Tuples.h" // for isTtype61 57 62 58 bool ctordtorp = false; // print all debug … … 187 183 }; 188 184 189 class FixCopyCtors final : public GenPoly::PolyMutator{185 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> { 190 186 public: 191 187 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} … … 194 190 static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount ); 195 191 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 ); 201 195 202 196 UnqCount & unqCount; … … 243 237 }; 244 238 245 class FixCtorExprs final : public GenPoly::DeclMutator { 246 public: 239 struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer { 247 240 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 248 241 static void fix( std::list< Declaration * > & translationUnit ); 249 242 250 using GenPoly::DeclMutator::mutate; 251 virtual Expression * mutate( ConstructorExpr * ctorExpr ) override; 243 Expression * postmutate( ConstructorExpr * ctorExpr ); 252 244 }; 253 245 } // namespace … … 316 308 317 309 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) { 318 FixCopyCtorsfixer( unqCount );310 PassVisitor<FixCopyCtors> fixer( unqCount ); 319 311 mutateAll( translationUnit, fixer ); 320 312 } … … 326 318 327 319 void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) { 328 FixCtorExprsfixer;329 fixer.mutateDeclarationList( translationUnit);320 PassVisitor<FixCtorExprs> fixer; 321 mutateAll( translationUnit, fixer ); 330 322 } 331 323 … … 339 331 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 340 332 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() ); 342 334 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) { 343 335 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); … … 368 360 } 369 361 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 ); } 373 363 374 364 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { … … 407 397 result = result->clone(); 408 398 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 ); 410 400 tmp->get_type()->set_const( false ); 411 401 … … 421 411 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 422 412 } 413 414 // set a unique name for the temporary once it's certain the call is necessary 415 tmp->name = tempNamer.newName(); 423 416 424 417 // replace argument to function call with temporary … … 450 443 result = result->clone(); 451 444 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 ); 453 446 ret->get_type()->set_const( false ); 454 447 impCpCtorExpr->get_returnDecls().push_back( ret ); 455 448 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 456 449 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 temporary450 // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 458 451 destructRet( ret, impCpCtorExpr ); 459 452 } … … 472 465 result = result->clone(); 473 466 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 ); 475 468 ret->get_type()->set_const( false ); 476 469 stmtExpr->get_returnDecls().push_front( ret ); … … 509 502 } else { 510 503 // 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 ) ); 512 505 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 513 506 } … … 515 508 } 516 509 517 Expression * FixCopyCtors:: mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {510 Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) { 518 511 CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 519 512 520 impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );521 513 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls(); 522 514 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls(); … … 525 517 // add all temporary declarations and their constructors 526 518 for ( ObjectDecl * obj : tempDecls ) { 527 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );519 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 528 520 } // for 529 521 for ( ObjectDecl * obj : returnDecls ) { 530 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );522 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 531 523 } // for 532 524 … … 536 528 } // for 537 529 538 // xxx - update to work with multiple return values539 530 ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front(); 540 531 Expression * callExpr = impCpCtorExpr->get_callExpr(); … … 569 560 } 570 561 571 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {562 void FixCopyCtors::premutate( StmtExpr * stmtExpr ) { 572 563 // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression, 573 564 // since temporaries can be shared across sub-expressions, e.g. 574 565 // [A, A] f(); 575 566 // g([A] x, [A] y); 576 // f(g());567 // g(f()); 577 568 // 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; 578 572 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids(); 579 573 for ( Statement *& stmt : stmts ) { 580 stmt = stmt->acceptMutator( * this);574 stmt = stmt->acceptMutator( *visitor ); 581 575 } // for 582 // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );583 576 assert( stmtExpr->get_result() ); 584 577 Type * result = stmtExpr->get_result(); 585 578 if ( ! result->isVoid() ) { 586 579 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) { 587 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );580 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 588 581 } // for 589 582 // add destructors after current statement … … 592 585 } // for 593 586 // 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() ); 596 588 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() ) ) ); 598 590 stmtExpr->get_returnDecls().clear(); 599 591 stmtExpr->get_dtors().clear(); … … 601 593 assert( stmtExpr->get_returnDecls().empty() ); 602 594 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; 607 599 unqCount[ unqExpr->get_id() ]--; 608 600 static std::unordered_map< int, std::list< Statement * > > dtors; 609 601 static std::unordered_map< int, UniqueExpr * > unqMap; 610 static std::unordered_set< int > addDeref;611 602 // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes 612 603 if ( unqMap.count( unqExpr->get_id() ) ) { … … 619 610 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 620 611 } 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 ); 628 615 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 ); 630 617 unqMap[unqExpr->get_id()] = unqExpr; 631 618 if ( unqCount[ unqExpr->get_id() ] == 0 ) { // insert destructor after the last use of the unique expression 632 619 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 633 620 } 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; 647 624 } 648 625 … … 819 796 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 820 797 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 821 800 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 822 // don't need to call intrinsic dtor, because it does nothing, but823 // non-intrinsic dtors must be called801 // set dtor location to the object's location for error messages 802 ctorInit->dtor->location = objDecl->location; 824 803 reverseDeclOrder.front().push_front( objDecl ); 825 804 } // if … … 1012 991 // skip non-DWT members 1013 992 if ( ! field ) continue; 993 // skip non-constructable members 994 if ( ! tryConstruct( field ) ) continue; 1014 995 // skip handled members 1015 996 if ( ! unhandled.count( field ) ) continue; … … 1142 1123 } 1143 1124 1144 Expression * FixCtorExprs:: mutate( ConstructorExpr * ctorExpr ) {1125 Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) { 1145 1126 static UniqueName tempNamer( "_tmp_ctor_expr" ); 1146 1127 // xxx - is the size check necessary? … … 1148 1129 1149 1130 // 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 ); 1152 1133 1153 1134 // xxx - this can be TupleAssignExpr now. Need to properly handle this case. … … 1158 1139 delete ctorExpr; 1159 1140 1141 // build assignment and replace constructor's first argument with new temporary 1160 1142 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 ) } ); 1181 1144 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; 1182 1151 1183 1152 // for constructor expr: … … 1188 1157 // T & tmp; 1189 1158 // &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 ) ) ); 1191 1160 commaExpr->set_env( env ); 1192 1161 return commaExpr; -
src/InitTweak/GenInit.cc
r201aeb9 rd67cdb7 26 26 #include "Common/UniqueName.h" // for UniqueName 27 27 #include "Common/utility.h" // for ValueGuard, maybeClone 28 #include "GenPoly/DeclMutator.h" // for DeclMutator29 28 #include "GenPoly/GenPoly.h" // for getFunctionType, isPolyType 30 29 #include "GenPoly/ScopedSet.h" // for ScopedSet, ScopedSet<>::const_iter... … … 62 61 }; 63 62 64 struct CtorDtor : public WithGuards, public WithShortCircuiting {63 struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor> { 65 64 /// create constructor and destructor statements for object declarations. 66 65 /// the actual call statements will be added in after the resolver has run … … 75 74 // that need to be constructed or destructed 76 75 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; } 83 79 84 80 void previsit( CompoundStmt * compoundStmt ); … … 96 92 }; 97 93 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 { 102 95 /// hoist dimension from array types in object declaration so that it uses a single 103 96 /// const variable of type size_t, so that side effecting array dimensions are only … … 105 98 static void hoistArrayDimension( std::list< Declaration * > & translationUnit ); 106 99 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 ); 112 103 // should not traverse into any of these declarations to find objects 113 104 // 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; } 122 108 123 109 void hoist( Type * type ); … … 128 114 129 115 void genInit( std::list< Declaration * > & translationUnit ) { 130 ReturnFixer::makeReturnTemp( translationUnit );116 fixReturnStatements( translationUnit ); 131 117 HoistArrayDimension::hoistArrayDimension( translationUnit ); 132 118 CtorDtor::generateCtorDtor( translationUnit ); 133 119 } 134 120 135 void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {121 void fixReturnStatements( std::list< Declaration * > & translationUnit ) { 136 122 PassVisitor<ReturnFixer> fixer; 137 123 mutateAll( translationUnit, fixer ); … … 143 129 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address 144 130 // 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() ) ) { 146 132 // explicitly construct the return value using the return expression and the retVal object 147 133 assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() ); … … 158 144 GuardValue( funcName ); 159 145 160 ftype = functionDecl-> get_functionType();161 funcName = functionDecl-> get_name();146 ftype = functionDecl->type; 147 funcName = functionDecl->name; 162 148 } 163 149 … … 165 151 // which would be incorrect if it is a side-effecting computation. 166 152 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 ); 172 159 storageClasses = objectDecl->get_storageClasses(); 173 DeclarationWithType * temp = Parent::mutate( objectDecl ); 160 } 161 162 DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) { 174 163 hoist( objectDecl->get_type() ); 175 return temp;164 return objectDecl; 176 165 } 177 166 … … 194 183 195 184 arrayType->set_dimension( new VariableExpr( arrayDimension ) ); 196 addDeclaration( arrayDimension );185 declsToAddBefore.push_back( arrayDimension ); 197 186 198 187 hoist( arrayType->get_base() ); … … 201 190 } 202 191 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 ); 208 194 } 209 195 … … 214 200 215 201 bool CtorDtor::isManaged( Type * type ) const { 216 // at least for now,references are never constructed202 // references are never constructed 217 203 if ( dynamic_cast< ReferenceType * >( type ) ) return false; 218 204 // need to clear and reset qualifiers when determining if a type is managed … … 221 207 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) { 222 208 // 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 ); }) ) { 224 210 return true; 225 211 } … … 305 291 306 292 void CtorDtor::previsit( FunctionDecl *functionDecl ) { 293 visit_children = false; // do not try and construct parameters or forall parameters 307 294 GuardValue( inFunction ); 308 295 inFunction = true; … … 318 305 } 319 306 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 ); 324 308 } 325 309 … … 340 324 } 341 325 342 void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt) {326 void CtorDtor::previsit( CompoundStmt * ) { 343 327 GuardScope( managedTypes ); 344 328 } -
src/InitTweak/GenInit.h
r201aeb9 rd67cdb7 25 25 void genInit( std::list< Declaration * > & translationUnit ); 26 26 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 ); 29 32 30 33 /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer -
src/InitTweak/InitTweak.cc
r201aeb9 rd67cdb7 1 #include <stddef.h> // for NULL2 1 #include <algorithm> // for find, all_of 3 2 #include <cassert> // for assertf, assert, strict_dynamic_cast … … 23 22 #include "SynTree/Type.h" // for FunctionType, ArrayType, PointerType 24 23 #include "SynTree/Visitor.h" // for Visitor, maybeAccept 24 #include "Tuples/Tuples.h" // for Tuples::isTtype 25 25 26 26 class UntypedValofExpr; … … 184 184 callExpr->get_args().splice( callExpr->get_args().end(), args ); 185 185 186 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL);186 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr ); 187 187 188 188 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); … … 250 250 // To accomplish this, generate switch statement, consuming all of expander's elements 251 251 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 252 if ( ! init ) return NULL;252 if ( ! init ) return nullptr; 253 253 CompoundStmt * block = new CompoundStmt( noLabels ); 254 254 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) ); 255 255 if ( block->get_kids().empty() ) { 256 256 delete block; 257 return NULL;257 return nullptr; 258 258 } else { 259 init = NULL; // init was consumed in creating the list init259 init = nullptr; // init was consumed in creating the list init 260 260 return block; 261 261 } 262 262 } 263 263 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; 266 266 } 267 267 … … 270 270 } 271 271 272 bool tryConstruct( ObjectDecl * objDecl ) { 272 bool tryConstruct( DeclarationWithType * dwt ) { 273 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); 274 if ( ! objDecl ) return false; 273 275 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 ); 277 284 } 278 285 … … 314 321 collectCtorDtorCalls( stmt, matches ); 315 322 assert( matches.size() <= 1 ); 316 return matches.size() == 1 ? matches.front() : NULL;323 return matches.size() == 1 ? matches.front() : nullptr; 317 324 } 318 325 … … 359 366 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) { 360 367 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ); 361 if ( ! appExpr ) return NULL;368 if ( ! appExpr ) return nullptr; 362 369 DeclarationWithType * function = getCalledFunction( appExpr->get_function() ); 363 370 assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() ); 364 371 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 365 372 // 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; 367 374 } 368 375 … … 482 489 return refType->get_base(); 483 490 } else { 484 return NULL;491 return nullptr; 485 492 } 486 493 } … … 488 495 Type * isPointerType( Type * type ) { 489 496 if ( getPointerBase( type ) ) return type; 490 else return NULL;497 else return nullptr; 491 498 } 492 499 -
src/InitTweak/InitTweak.h
r201aeb9 rd67cdb7 33 33 std::list< Expression * > makeInitList( Initializer * init ); 34 34 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 ); 37 40 38 41 /// True if the Initializer contains designations -
src/Makefile.in
r201aeb9 rd67cdb7 172 172 GenPoly/driver_cfa_cpp-Box.$(OBJEXT) \ 173 173 GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT) \ 174 GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT) \175 174 GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT) \ 176 175 GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT) \ … … 178 177 GenPoly/driver_cfa_cpp-CopyParams.$(OBJEXT) \ 179 178 GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \ 180 GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT) \181 179 GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT) \ 182 180 InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT) \ … … 253 251 SynTree/driver_cfa_cpp-Visitor.$(OBJEXT) \ 254 252 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \ 255 SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT) \256 253 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \ 257 254 SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \ … … 497 494 ControlStruct/ForExprMutator.cc \ 498 495 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 \ 503 499 InitTweak/GenInit.cc InitTweak/FixInit.cc \ 504 500 InitTweak/FixGlobalInit.cc InitTweak/InitTweak.cc \ … … 535 531 SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \ 536 532 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/Tuple Assignment.cc Tuples/TupleExpansion.cc \540 Tuples/Explode.ccVirtual/ExpandCasts.cc533 SynTree/TypeSubstitution.cc SynTree/Attribute.cc \ 534 SynTree/VarExprReplacer.cc Tuples/TupleAssignment.cc \ 535 Tuples/TupleExpansion.cc Tuples/Explode.cc \ 536 Virtual/ExpandCasts.cc 541 537 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \ 542 538 ${cfa_cpplib_PROGRAMS}} … … 717 713 GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT): GenPoly/$(am__dirstamp) \ 718 714 GenPoly/$(DEPDIR)/$(am__dirstamp) 719 GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \720 GenPoly/$(DEPDIR)/$(am__dirstamp)721 715 GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT): GenPoly/$(am__dirstamp) \ 722 716 GenPoly/$(DEPDIR)/$(am__dirstamp) … … 729 723 GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT): \ 730 724 GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp) 731 GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \732 GenPoly/$(DEPDIR)/$(am__dirstamp)733 725 GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT): \ 734 726 GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp) … … 929 921 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT): SynTree/$(am__dirstamp) \ 930 922 SynTree/$(DEPDIR)/$(am__dirstamp) 931 SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT): \932 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)933 923 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT): \ 934 924 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp) … … 1008 998 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Po@am__quote@ 1009 999 @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@1011 1000 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po@am__quote@ 1012 1001 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po@am__quote@ 1013 1002 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po@am__quote@ 1014 1003 @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@1016 1004 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po@am__quote@ 1017 1005 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po@am__quote@ … … 1056 1044 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Po@am__quote@ 1057 1045 @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@1059 1046 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po@am__quote@ 1060 1047 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Po@am__quote@ … … 1450 1437 @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` 1451 1438 1452 GenPoly/driver_cfa_cpp-PolyMutator.o: GenPoly/PolyMutator.cc1453 @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.cc1454 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po1455 @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.cc1458 1459 GenPoly/driver_cfa_cpp-PolyMutator.obj: GenPoly/PolyMutator.cc1460 @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.Po1462 @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 1466 1439 GenPoly/driver_cfa_cpp-ScrubTyVars.o: GenPoly/ScrubTyVars.cc 1467 1440 @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 … … 1534 1507 @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` 1535 1508 1536 GenPoly/driver_cfa_cpp-DeclMutator.o: GenPoly/DeclMutator.cc1537 @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.cc1538 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Po1539 @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.cc1542 1543 GenPoly/driver_cfa_cpp-DeclMutator.obj: GenPoly/DeclMutator.cc1544 @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.Po1546 @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 1550 1509 GenPoly/driver_cfa_cpp-InstantiateGeneric.o: GenPoly/InstantiateGeneric.cc 1551 1510 @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 … … 2583 2542 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2584 2543 @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.cc2587 @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.cc2588 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po2589 @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.cc2592 2593 SynTree/driver_cfa_cpp-AddStmtVisitor.obj: SynTree/AddStmtVisitor.cc2594 @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.Po2596 @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`2599 2544 2600 2545 SynTree/driver_cfa_cpp-TypeSubstitution.o: SynTree/TypeSubstitution.cc -
src/Parser/StatementNode.cc
r201aeb9 rd67cdb7 234 234 target, 235 235 maybeMoveBuild<Statement >( stmt ), 236 maybeMoveBuild<Expression>( when)236 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 237 237 }); 238 238 … … 250 250 delete targetExpr; 251 251 252 node->clauses. push_back(WaitForStmt::Clause{252 node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{ 253 253 std::move( target ), 254 254 maybeMoveBuild<Statement >( stmt ), 255 maybeMoveBuild<Expression>( when)255 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 256 256 }); 257 257 … … 265 265 node->timeout.time = maybeMoveBuild<Expression>( timeout ); 266 266 node->timeout.statement = maybeMoveBuild<Statement >( stmt ); 267 node->timeout.condition = maybeMoveBuild<Expression>( when);267 node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 268 268 } 269 269 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 ) ); 272 272 } 273 273 … … 280 280 node->timeout.time = maybeMoveBuild<Expression>( timeout ); 281 281 node->timeout.statement = maybeMoveBuild<Statement >( stmt ); 282 node->timeout.condition = maybeMoveBuild<Expression>( when);282 node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 283 283 284 284 node->orelse.statement = maybeMoveBuild<Statement >( else_stmt ); 285 node->orelse.condition = maybeMoveBuild<Expression>( else_when);285 node->orelse.condition = notZeroExpr( maybeMoveBuild<Expression>( else_when ) ); 286 286 287 287 return node; 288 288 } 289 290 // WaitForStmt::Target build_waitfor( const std::string * name, ExpressionNode * arguments ) {291 // return WaitForStmt::Clause{292 293 // };294 // }295 289 296 290 Statement *build_compound( StatementNode *first ) { -
src/Parser/parserutility.cc
r201aeb9 rd67cdb7 29 29 30 30 Expression *notZeroExpr( Expression *orig ) { 31 if( !orig ) return nullptr; 31 32 UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) ); 32 33 comparison->get_args().push_back( orig ); -
src/ResolvExpr/AlternativeFinder.cc
r201aeb9 rd67cdb7 144 144 expr->get_result()->accept( global_renamer ); 145 145 } 146 147 void referenceToRvalueConversion( Expression *& expr ) {148 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {149 // cast away reference from expr150 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );151 }152 }153 146 } // 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 } 154 154 155 155 template< typename InputIterator, typename OutputIterator > -
src/ResolvExpr/AlternativeFinder.h
r201aeb9 rd67cdb7 50 50 const SymTab::Indexer &get_indexer() const { return indexer; } 51 51 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 ); 52 57 private: 53 58 virtual void visit( ApplicationExpr *applicationExpr ); … … 81 86 virtual void visit( StmtExpr *stmtExpr ); 82 87 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 );87 88 88 89 /// Adds alternatives for anonymous members … … 108 109 109 110 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ); 111 void referenceToRvalueConversion( Expression *& expr ); 110 112 111 113 template< typename InputIterator, typename OutputIterator > -
src/ResolvExpr/Resolver.cc
r201aeb9 rd67cdb7 40 40 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 41 41 #include "typeops.h" // for extractResultType 42 #include "Unify.h" // for unify 42 43 43 44 using namespace std; … … 71 72 void previsit( ThrowStmt *throwStmt ); 72 73 void previsit( CatchStmt *catchStmt ); 74 void previsit( WaitForStmt * stmt ); 73 75 74 76 void previsit( SingleInit *singleInit ); … … 93 95 PassVisitor<Resolver> resolver; 94 96 acceptAll( translationUnit, resolver ); 97 } 98 99 void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) { 100 PassVisitor<Resolver> resolver( indexer ); 101 maybeAccept( decl, resolver ); 95 102 } 96 103 … … 116 123 } 117 124 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 118 146 namespace { 119 Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {120 TypeEnvironment env;121 AlternativeFinder finder( indexer, env );122 finder.find( untyped );123 #if 0124 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 } // for131 } // if132 #endif133 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 140 147 bool isIntegralType( Type *type ) { 141 148 if ( dynamic_cast< EnumInstType * >( type ) ) { … … 391 398 } 392 399 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 393 603 template< typename T > 394 604 bool isCharType( T t ) { -
src/ResolvExpr/Resolver.h
r201aeb9 rd67cdb7 29 29 /// Checks types and binds syntactic constructs to typed representations 30 30 void resolve( std::list< Declaration * > translationUnit ); 31 void resolveDecl( Declaration *, const SymTab::Indexer &indexer ); 31 32 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ); 32 33 Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ); 34 Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ); 33 35 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ); 34 36 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ); -
src/ResolvExpr/TypeEnvironment.cc
r201aeb9 rd67cdb7 123 123 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) { 124 124 for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) { 125 /// std::c out<< "adding " << *theVar;125 /// std::cerr << "adding " << *theVar; 126 126 if ( theClass->type ) { 127 /// std::c out<< " bound to ";128 /// theClass->type->print( std::c out);129 /// std::c out<< std::endl;127 /// std::cerr << " bound to "; 128 /// theClass->type->print( std::cerr ); 129 /// std::cerr << std::endl; 130 130 sub.add( *theVar, theClass->type ); 131 131 } else if ( theVar != theClass->vars.begin() ) { 132 132 TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype ); 133 /// std::c out<< " bound to variable " << *theClass->vars.begin() << std::endl;133 /// std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl; 134 134 sub.add( *theVar, newTypeInst ); 135 135 delete newTypeInst; -
src/SymTab/Autogen.cc
r201aeb9 rd67cdb7 16 16 #include "Autogen.h" 17 17 18 #include <cstddef> // for NULL19 18 #include <algorithm> // for count_if 20 19 #include <cassert> // for strict_dynamic_cast, assert, assertf … … 27 26 #include "AddVisit.h" // for addVisit 28 27 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 28 #include "Common/PassVisitor.h" // for PassVisitor 29 29 #include "Common/ScopedMap.h" // for ScopedMap<>::const_iterator, Scope... 30 30 #include "Common/utility.h" // for cloneAll, operator+ 31 #include "GenPoly/DeclMutator.h" // for DeclMutator32 31 #include "GenPoly/ScopedSet.h" // for ScopedSet, ScopedSet<>::iterator 32 #include "InitTweak/GenInit.h" // for fixReturnStatements 33 #include "ResolvExpr/Resolver.h" // for resolveDecl 33 34 #include "SymTab/Mangler.h" // for Mangler 34 35 #include "SynTree/Attribute.h" // For Attribute … … 53 54 }; 54 55 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 { 66 57 AutogenerateRoutines(); 67 58 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 ); 80 70 81 71 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; 86 73 unsigned int functionNesting = 0; // current level of nested functions 87 74 /// Note: the following maps could be ScopedSets, but it should be easier to work … … 93 80 94 81 /// 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 ); 107 88 108 89 private: … … 112 93 113 94 void autogenerateRoutines( std::list< Declaration * > &translationUnit ) { 114 AutogenerateRoutinesgenerator;115 acceptA ndAdd( translationUnit, generator );95 PassVisitor<AutogenerateRoutines> generator; 96 acceptAll( translationUnit, generator ); 116 97 117 98 // needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc. 118 99 // AutogenTupleRoutines tupleGenerator; 119 // tupleGenerator.mutateDeclarationList( translationUnit);100 // acceptAll( translationUnit, tupleGenerator ); 120 101 } 121 102 122 103 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; 124 105 } 125 106 … … 128 109 FunctionDecl * decl = functionDecl->clone(); 129 110 delete decl->get_statements(); 130 decl->set_statements( NULL);111 decl->set_statements( nullptr ); 131 112 declsToAdd.push_back( decl ); 132 113 decl->fixUniqueId(); … … 339 320 assert( ! func->get_functionType()->get_parameters().empty() ); 340 321 ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() ); 341 ObjectDecl * srcParam = NULL;322 ObjectDecl * srcParam = nullptr; 342 323 if ( func->get_functionType()->get_parameters().size() == 2 ) { 343 324 srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() ); … … 346 327 assert( dstParam ); 347 328 348 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;329 Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr; 349 330 makeStructMemberOp( dstParam, srcselect, field, func, forward ); 350 331 } // if … … 385 366 } else { 386 367 // no matching parameter, initialize field with default ctor 387 makeStructMemberOp( dstParam, NULL, field, func );368 makeStructMemberOp( dstParam, nullptr, field, func ); 388 369 } 389 370 } … … 401 382 void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) { 402 383 // 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() ) ) { 405 385 return; 406 386 } 407 387 408 388 // 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 functions389 const std::list< TypeDecl * > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions 410 390 411 391 // generate each of the functions based on the supplied FuncData objects … … 572 552 // the order here determines the order that these functions are generated. 573 553 // 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; 581 562 if ( ! enumDecl->get_members().empty() ) { 582 563 EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() ); … … 586 567 } 587 568 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 ) { 592 574 // 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 ) ) ); 595 577 } 596 578 structInst.set_baseStruct( structDecl ); 597 579 makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data ); 598 structsDone.insert( structDecl-> get_name());580 structsDone.insert( structDecl->name ); 599 581 } // if 600 582 } 601 583 602 void AutogenerateRoutines::visit( UnionDecl *unionDecl ) { 584 void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) { 585 visit_children = false; 603 586 if ( ! unionDecl->get_members().empty() ) { 604 587 UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() ); … … 619 602 620 603 // 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; 622 606 if ( ! typeDecl->base ) return; 623 607 … … 664 648 } 665 649 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 *) { 674 651 // 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 *) { 678 656 // 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 * ) { 682 661 // 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; 693 667 // record the existence of this function as appropriate 694 668 insert( functionDecl, constructable, InitTweak::isDefaultConstructor ); … … 697 671 insert( functionDecl, destructable, InitTweak::isDestructor ); 698 672 699 maybeAccept( functionDecl-> get_functionType(), *this);673 maybeAccept( functionDecl->type, *visitor ); 700 674 functionNesting += 1; 701 maybeAccept( functionDecl-> get_statements(), *this);675 maybeAccept( functionDecl->statements, *visitor ); 702 676 functionNesting -= 1; 703 677 } 704 678 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 ); 719 685 } 720 686 … … 734 700 } 735 701 736 Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) { 737 tupleType = strict_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) ); 702 void AutogenTupleRoutines::postvisit( TupleType * tupleType ) { 738 703 std::string mangleName = SymTab::Mangler::mangleType( tupleType ); 739 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;704 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return; 740 705 seenTuples.insert( mangleName ); 741 706 … … 785 750 makeTupleFunctionBody( dtorDecl ); 786 751 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 ); 797 761 functionNesting += 1; 798 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ));762 maybeAccept( functionDecl->statements, *visitor ); 799 763 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 ); 808 768 } 809 769 } // SymTab -
src/SymTab/FixFunction.cc
r201aeb9 rd67cdb7 27 27 28 28 DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) { 29 // can't delete function type because it may contain assertions, so transfer ownership to new object 29 30 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() ); 30 31 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; 33 33 delete functionDecl; 34 34 return pointer; -
src/SymTab/Indexer.cc
r201aeb9 rd67cdb7 40 40 41 41 namespace 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 55 42 typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable; 56 43 typedef std::unordered_map< std::string, MangleTable > IdTable; … … 198 185 } 199 186 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 ) { 205 192 that.tables = 0; 206 193 } -
src/SymTab/Indexer.h
r201aeb9 rd67cdb7 26 26 class Indexer { 27 27 public: 28 explicit Indexer( bool useDebug = false);28 explicit Indexer(); 29 29 30 30 Indexer( const Indexer &that ); … … 76 76 void addTrait( TraitDecl *decl ); 77 77 78 bool doDebug = false; ///< Display debugging trace? 78 79 private: 79 80 struct Impl; … … 81 82 Impl *tables; ///< Copy-on-write instance of table data structure 82 83 unsigned long scope; ///< Scope index of this pointer 83 bool doDebug; ///< Display debugging trace?84 84 85 85 /// Takes a new ref to a table (returns null if null) -
src/SymTab/Mangler.cc
r201aeb9 rd67cdb7 31 31 32 32 namespace SymTab { 33 std::string Mangler::mangleType( Type * ty ) {33 std::string Mangler::mangleType( Type * ty ) { 34 34 Mangler mangler( false, true ); 35 35 maybeAccept( ty, mangler ); … … 48 48 } 49 49 50 void Mangler::mangleDecl( DeclarationWithType * declaration ) {50 void Mangler::mangleDecl( DeclarationWithType * declaration ) { 51 51 bool wasTopLevel = isTopLevel; 52 52 if ( isTopLevel ) { … … 79 79 } 80 80 81 void Mangler::visit( ObjectDecl * declaration ) {81 void Mangler::visit( ObjectDecl * declaration ) { 82 82 mangleDecl( declaration ); 83 83 } 84 84 85 void Mangler::visit( FunctionDecl * declaration ) {85 void Mangler::visit( FunctionDecl * declaration ) { 86 86 mangleDecl( declaration ); 87 87 } 88 88 89 void Mangler::visit( VoidType * voidType ) {89 void Mangler::visit( VoidType * voidType ) { 90 90 printQualifiers( voidType ); 91 91 mangleName << "v"; 92 92 } 93 93 94 void Mangler::visit( BasicType * basicType ) {94 void Mangler::visit( BasicType * basicType ) { 95 95 static const char *btLetter[] = { 96 96 "b", // Bool … … 123 123 } 124 124 125 void Mangler::visit( PointerType * pointerType ) {125 void Mangler::visit( PointerType * pointerType ) { 126 126 printQualifiers( pointerType ); 127 127 mangleName << "P"; … … 129 129 } 130 130 131 void Mangler::visit( ArrayType * arrayType ) {131 void Mangler::visit( ArrayType * arrayType ) { 132 132 // TODO: encode dimension 133 133 printQualifiers( arrayType ); … … 136 136 } 137 137 138 void Mangler::visit( ReferenceType * refType ) {138 void Mangler::visit( ReferenceType * refType ) { 139 139 printQualifiers( refType ); 140 140 mangleName << "R"; … … 151 151 } 152 152 153 void Mangler::visit( FunctionType * functionType ) {153 void Mangler::visit( FunctionType * functionType ) { 154 154 printQualifiers( functionType ); 155 155 mangleName << "F"; … … 162 162 } 163 163 164 void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {164 void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) { 165 165 printQualifiers( refType ); 166 166 … … 168 168 } 169 169 170 void Mangler::mangleGenericRef( ReferenceToType * refType, std::string prefix ) {170 void Mangler::mangleGenericRef( ReferenceToType * refType, std::string prefix ) { 171 171 printQualifiers( refType ); 172 172 … … 191 191 } 192 192 193 void Mangler::visit( StructInstType * aggregateUseType ) {193 void Mangler::visit( StructInstType * aggregateUseType ) { 194 194 if ( typeMode ) mangleGenericRef( aggregateUseType, "s" ); 195 195 else mangleRef( aggregateUseType, "s" ); 196 196 } 197 197 198 void Mangler::visit( UnionInstType * aggregateUseType ) {198 void Mangler::visit( UnionInstType * aggregateUseType ) { 199 199 if ( typeMode ) mangleGenericRef( aggregateUseType, "u" ); 200 200 else mangleRef( aggregateUseType, "u" ); 201 201 } 202 202 203 void Mangler::visit( EnumInstType * aggregateUseType ) {203 void Mangler::visit( EnumInstType * aggregateUseType ) { 204 204 mangleRef( aggregateUseType, "e" ); 205 205 } 206 206 207 void Mangler::visit( TypeInstType * typeInst ) {207 void Mangler::visit( TypeInstType * typeInst ) { 208 208 VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); 209 209 if ( varNum == varNums.end() ) { … … 233 233 } 234 234 235 void Mangler::visit( TupleType * tupleType ) {235 void Mangler::visit( TupleType * tupleType ) { 236 236 printQualifiers( tupleType ); 237 237 mangleName << "T"; 238 acceptAll( tupleType-> get_types(), *this );238 acceptAll( tupleType->types, *this ); 239 239 mangleName << "_"; 240 240 } 241 241 242 void Mangler::visit( VarArgsType * varArgsType ) {242 void Mangler::visit( VarArgsType * varArgsType ) { 243 243 printQualifiers( varArgsType ); 244 244 mangleName << "VARGS"; 245 245 } 246 246 247 void Mangler::visit( __attribute__((unused)) ZeroType *zeroType) {247 void Mangler::visit( ZeroType * ) { 248 248 mangleName << "Z"; 249 249 } 250 250 251 void Mangler::visit( __attribute__((unused)) OneType *oneType) {251 void Mangler::visit( OneType * ) { 252 252 mangleName << "O"; 253 253 } 254 254 255 void Mangler::visit( TypeDecl * decl ) {255 void Mangler::visit( TypeDecl * decl ) { 256 256 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; 258 258 } 259 259 … … 264 264 } 265 265 266 void Mangler::printQualifiers( Type * type ) {266 void Mangler::printQualifiers( Type * type ) { 267 267 // skip if not including qualifiers 268 268 if ( typeMode ) return; … … 272 272 int tcount = 0, dcount = 0, fcount = 0, vcount = 0; 273 273 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 ) { 275 275 switch ( (*i)->get_kind() ) { 276 276 case TypeDecl::Any: … … 289 289 assert( false ); 290 290 } // 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 ) { 293 293 Mangler sub_mangler( mangleOverridable, typeMode ); 294 294 sub_mangler.nextVarNum = nextVarNum; … … 309 309 mangleName << "V"; 310 310 } // if 311 if ( type->get_mutex() ) { 312 mangleName << "M"; 313 } // if 311 314 // Removed due to restrict not affecting function compatibility in GCC 312 315 // if ( type->get_isRestrict() ) { … … 314 317 // } // if 315 318 if ( type->get_lvalue() ) { 319 // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues 316 320 mangleName << "L"; 317 } // if321 } 318 322 if ( type->get_atomic() ) { 319 323 mangleName << "A"; -
src/SymTab/Validate.cc
r201aeb9 rd67cdb7 56 56 #include "FixFunction.h" // for FixFunction 57 57 #include "Indexer.h" // for Indexer 58 #include "InitTweak/GenInit.h" // for fixReturnStatements 58 59 #include "InitTweak/InitTweak.h" // for isCtorDtorAssign 59 60 #include "Parser/LinkageSpec.h" // for C … … 150 151 /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID. 151 152 struct ForallPointerDecay final { 152 void previsit( ObjectDecl * object );153 void previsit( FunctionDecl * func );153 void previsit( ObjectDecl * object ); 154 void previsit( FunctionDecl * func ); 154 155 }; 155 156 … … 579 580 580 581 /// Fix up assertions - flattens assertion lists, removing all trait instances 581 void forallFixer( Type * func) {582 for ( TypeDecl * type : f unc->get_forall()) {582 void forallFixer( std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) { 583 for ( TypeDecl * type : forall ) { 583 584 std::list< DeclarationWithType * > asserts; 584 585 asserts.splice( asserts.end(), type->assertions ); … … 599 600 assertion = assertion->acceptMutator( fixer ); 600 601 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 ); 602 603 } // if 603 604 } // for … … 607 608 608 609 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 ); 612 613 } // if 613 614 object->fixUniqueId(); … … 615 616 616 617 void ForallPointerDecay::previsit( FunctionDecl *func ) { 617 forallFixer( func-> get_type());618 forallFixer( func->type->forall, func ); 618 619 func->fixUniqueId(); 619 620 } -
src/SynTree/BaseSyntaxNode.h
r201aeb9 rd67cdb7 26 26 27 27 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; 29 29 }; 30 31 std::ostream & operator<<( std::ostream & out, const BaseSyntaxNode * node ); 30 32 31 33 // Local Variables: // -
src/SynTree/CompoundStmt.cc
r201aeb9 rd67cdb7 29 29 30 30 CompoundStmt::CompoundStmt( std::list<Label> labels ) : Statement( labels ) { 31 } 32 33 CompoundStmt::CompoundStmt( std::list<Statement *> stmts ) : Statement( noLabels ), kids( stmts ) { 31 34 } 32 35 -
src/SynTree/Constant.cc
r201aeb9 rd67cdb7 32 32 Constant Constant::from_bool( bool b ) { 33 33 return Constant( new BasicType( Type::Qualifiers(), BasicType::Bool ), b ? "1" : "0" , (unsigned long long int)b ); 34 } 35 36 Constant Constant::from_char( char c ) { 37 return Constant( new BasicType( Type::Qualifiers(), BasicType::Char ), std::to_string( c ), (unsigned long long int)c ); 34 38 } 35 39 -
src/SynTree/Constant.h
r201aeb9 rd67cdb7 40 40 /// generates a boolean constant of the given bool 41 41 static Constant from_bool( bool b ); 42 /// generates a char constant of the given char 43 static Constant from_char( char c ); 42 44 /// generates an integer constant of the given int 43 45 static Constant from_int( int i ); -
src/SynTree/Declaration.cc
r201aeb9 rd67cdb7 59 59 } 60 60 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 70 61 71 62 AsmDecl::AsmDecl( AsmStmt *stmt ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), stmt( stmt ) { -
src/SynTree/Declaration.h
r201aeb9 rd67cdb7 62 62 void fixUniqueId( void ); 63 63 virtual Declaration *clone() const = 0; 64 virtual void accept( Visitor &v ) = 0;64 virtual void accept( Visitor &v ) override = 0; 65 65 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; 67 67 virtual void printShort( std::ostream &os, int indent = 0 ) const = 0; 68 68 … … 106 106 //void set_functionSpecifiers( Type::FuncSpecifiers newValue ) { fs = newValue; } 107 107 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; 110 110 111 111 virtual Type * get_type() const = 0; … … 128 128 virtual ~ObjectDecl(); 129 129 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; } 132 132 133 133 Initializer *get_init() const { return init; } … … 139 139 static ObjectDecl * newObject( const std::string & name, Type * type, Initializer * init ); 140 140 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; 146 146 }; 147 147 … … 157 157 virtual ~FunctionDecl(); 158 158 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 ); } 161 161 162 162 FunctionType * get_functionType() const { return type; } … … 165 165 void set_statements( CompoundStmt *newValue ) { statements = newValue; } 166 166 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; 172 172 }; 173 173 … … 190 190 virtual std::string typeString() const = 0; 191 191 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; 195 195 }; 196 196 … … 227 227 TypeDecl * set_sized( bool newValue ) { sized = newValue; return this; } 228 228 229 virtual std::string typeString() const ;229 virtual std::string typeString() const override; 230 230 virtual std::string genTypeString() const; 231 231 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; 236 236 237 237 private: … … 245 245 TypedefDecl( const TypedefDecl &other ) : Parent( other ) {} 246 246 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 ); } 252 252 private: 253 253 }; … … 274 274 AggregateDecl * set_body( bool body ) { AggregateDecl::body = body; return this; } 275 275 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; 278 278 protected: 279 279 virtual std::string typeString() const = 0; … … 290 290 bool is_thread() { return kind == DeclarationNode::Thread; } 291 291 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 ); } 295 295 private: 296 296 DeclarationNode::Aggregate kind; 297 virtual std::string typeString() const ;297 virtual std::string typeString() const override; 298 298 }; 299 299 … … 304 304 UnionDecl( const UnionDecl &other ) : Parent( other ) {} 305 305 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; 311 311 }; 312 312 … … 317 317 EnumDecl( const EnumDecl &other ) : Parent( other ) {} 318 318 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; 324 324 }; 325 325 … … 332 332 TraitDecl( const TraitDecl &other ) : Parent( other ) {} 333 333 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; 339 339 }; 340 340 … … 350 350 void set_stmt( AsmStmt *newValue ) { stmt = newValue; } 351 351 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 360 359 std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data ); 361 360 -
src/SynTree/Expression.cc
r201aeb9 rd67cdb7 741 741 } 742 742 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 753 743 // Local Variables: // 754 744 // tab-width: 4 // -
src/SynTree/Expression.h
r201aeb9 rd67cdb7 821 821 }; 822 822 823 824 std::ostream & operator<<( std::ostream & out, const Expression * expr );825 826 823 // Local Variables: // 827 824 // tab-width: 4 // -
src/SynTree/Initializer.cc
r201aeb9 rd67cdb7 137 137 } 138 138 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 157 139 // Local Variables: // 158 140 // tab-width: 4 // -
src/SynTree/Initializer.h
r201aeb9 rd67cdb7 38 38 39 39 virtual Designation * clone() const { return new Designation( *this ); }; 40 virtual void accept( Visitor &v ) { v.visit( this ); }