Changeset d67cdb7
- Timestamp:
- Sep 26, 2017, 11:27:38 PM (8 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 ); }40 virtual void accept( Visitor &v ) override { v.visit( this ); } 41 41 virtual Designation * acceptMutator( Mutator &m ) { return m.mutate( this ); } 42 virtual void print( std::ostream &os, int indent = 0 ) const ;42 virtual void print( std::ostream &os, int indent = 0 ) const override; 43 43 }; 44 44 … … 55 55 56 56 virtual Initializer *clone() const = 0; 57 virtual void accept( Visitor &v ) = 0;57 virtual void accept( Visitor &v ) override = 0; 58 58 virtual Initializer *acceptMutator( Mutator &m ) = 0; 59 virtual void print( std::ostream &os, int indent = 0 ) const = 0;59 virtual void print( std::ostream &os, int indent = 0 ) const override = 0; 60 60 private: 61 61 bool maybeConstructed; … … 75 75 void set_value( Expression *newValue ) { value = newValue; } 76 76 77 virtual SingleInit *clone() const { return new SingleInit( *this); }78 virtual void accept( Visitor &v ) { v.visit( this ); }79 virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }80 virtual void print( std::ostream &os, int indent = 0 ) const ;77 virtual SingleInit *clone() const override { return new SingleInit( *this); } 78 virtual void accept( Visitor &v ) override { v.visit( this ); } 79 virtual Initializer *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 80 virtual void print( std::ostream &os, int indent = 0 ) const override; 81 81 }; 82 82 … … 103 103 const_iterator end() const { return initializers.end(); } 104 104 105 virtual ListInit *clone() const { return new ListInit( *this ); }106 virtual void accept( Visitor &v ) { v.visit( this ); }107 virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }108 virtual void print( std::ostream &os, int indent = 0 ) const ;105 virtual ListInit *clone() const override { return new ListInit( *this ); } 106 virtual void accept( Visitor &v ) override { v.visit( this ); } 107 virtual Initializer *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 108 virtual void print( std::ostream &os, int indent = 0 ) const override; 109 109 }; 110 110 … … 129 129 Initializer * get_init() const { return init; } 130 130 131 ConstructorInit *clone() const { return new ConstructorInit( *this ); }132 virtual void accept( Visitor &v ) { v.visit( this ); }133 virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }134 virtual void print( std::ostream &os, int indent = 0 ) const ;131 ConstructorInit *clone() const override { return new ConstructorInit( *this ); } 132 virtual void accept( Visitor &v ) override { v.visit( this ); } 133 virtual Initializer *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 134 virtual void print( std::ostream &os, int indent = 0 ) const override; 135 135 136 136 private: … … 140 140 }; 141 141 142 std::ostream & operator<<( std::ostream & out, const Initializer * init );143 std::ostream & operator<<( std::ostream & out, const Designation * des );144 145 142 // Local Variables: // 146 143 // tab-width: 4 // -
src/SynTree/Statement.cc
r201aeb9 rd67cdb7 168 168 } 169 169 170 SwitchStmt::SwitchStmt( std::list<Label> labels, Expression * condition, std::list<Statement *> &statements ):170 SwitchStmt::SwitchStmt( std::list<Label> labels, Expression * condition, const std::list<Statement *> &statements ): 171 171 Statement( labels ), condition( condition ), statements( statements ) { 172 172 } … … 196 196 } 197 197 198 CaseStmt::CaseStmt( std::list<Label> labels, Expression *condition, std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) :198 CaseStmt::CaseStmt( std::list<Label> labels, Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) : 199 199 Statement( labels ), condition( condition ), stmts( statements ), _isDefault( deflt ) { 200 200 if ( isDefault() && condition != 0 ) … … 497 497 } 498 498 499 std::ostream & operator<<( std::ostream & out, const Statement * statement ) {500 if ( statement ) {501 statement->print( out );502 } else {503 out << "nullptr";504 }505 return out;506 }507 508 499 // Local Variables: // 509 500 // tab-width: 4 // -
src/SynTree/Statement.h
r201aeb9 rd67cdb7 44 44 45 45 virtual Statement *clone() const = 0; 46 virtual void accept( Visitor &v ) = 0;46 virtual void accept( Visitor &v ) override = 0; 47 47 virtual Statement *acceptMutator( Mutator &m ) = 0; 48 virtual void print( std::ostream &os, int indent = 0 ) const ;48 virtual void print( std::ostream &os, int indent = 0 ) const override; 49 49 }; 50 50 … … 54 54 55 55 CompoundStmt( std::list<Label> labels ); 56 CompoundStmt( std::list<Statement *> stmts ); 56 57 CompoundStmt( const CompoundStmt &other ); 57 58 virtual ~CompoundStmt(); … … 61 62 void push_front( Statement * stmt ) { kids.push_front( stmt ); } 62 63 63 virtual CompoundStmt *clone() const { return new CompoundStmt( *this ); }64 virtual void accept( Visitor &v ) { v.visit( this ); }65 virtual CompoundStmt *acceptMutator( Mutator &m ) { return m.mutate( this ); }66 virtual void print( std::ostream &os, int indent = 0 ) const ;64 virtual CompoundStmt *clone() const override { return new CompoundStmt( *this ); } 65 virtual void accept( Visitor &v ) override { v.visit( this ); } 66 virtual CompoundStmt *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 67 virtual void print( std::ostream &os, int indent = 0 ) const override; 67 68 }; 68 69 … … 72 73 NullStmt( std::list<Label> labels ); 73 74 74 virtual NullStmt *clone() const { return new NullStmt( *this ); }75 virtual void accept( Visitor &v ) { v.visit( this ); }76 virtual NullStmt *acceptMutator( Mutator &m ) { return m.mutate( this ); }77 virtual void print( std::ostream &os, int indent = 0 ) const ;75 virtual NullStmt *clone() const override { return new NullStmt( *this ); } 76 virtual void accept( Visitor &v ) override { v.visit( this ); } 77 virtual NullStmt *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 78 virtual void print( std::ostream &os, int indent = 0 ) const override; 78 79 }; 79 80 … … 89 90 void set_expr( Expression *newValue ) { expr = newValue; } 90 91 91 virtual ExprStmt *clone() const { return new ExprStmt( *this ); }92 virtual void accept( Visitor &v ) { v.visit( this ); }93 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }94 virtual void print( std::ostream &os, int indent = 0 ) const ;92 virtual ExprStmt *clone() const override { return new ExprStmt( *this ); } 93 virtual void accept( Visitor &v ) override { v.visit( this ); } 94 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 95 virtual void print( std::ostream &os, int indent = 0 ) const override; 95 96 }; 96 97 … … 146 147 void set_elsePart( Statement *newValue ) { elsePart = newValue; } 147 148 148 virtual IfStmt *clone() const { return new IfStmt( *this ); }149 virtual void accept( Visitor &v ) { v.visit( this ); }150 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }151 virtual void print( std::ostream &os, int indent = 0 ) const ;149 virtual IfStmt *clone() const override { return new IfStmt( *this ); } 150 virtual void accept( Visitor &v ) override { v.visit( this ); } 151 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 152 virtual void print( std::ostream &os, int indent = 0 ) const override; 152 153 }; 153 154 … … 157 158 std::list<Statement *> statements; 158 159 159 SwitchStmt( std::list<Label> labels, Expression *condition, std::list<Statement *> &statements );160 SwitchStmt( std::list<Label> labels, Expression *condition, const std::list<Statement *> &statements ); 160 161 SwitchStmt( const SwitchStmt &other ); 161 162 virtual ~SwitchStmt(); … … 166 167 std::list<Statement *> & get_statements() { return statements; } 167 168 168 virtual void accept( Visitor &v ) { v.visit( this ); }169 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }170 171 virtual SwitchStmt *clone() const { return new SwitchStmt( *this ); }172 virtual void print( std::ostream &os, int indent = 0 ) const ;169 virtual void accept( Visitor &v ) override { v.visit( this ); } 170 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 171 172 virtual SwitchStmt *clone() const override { return new SwitchStmt( *this ); } 173 virtual void print( std::ostream &os, int indent = 0 ) const override; 173 174 174 175 }; … … 179 180 std::list<Statement *> stmts; 180 181 181 CaseStmt( std::list<Label> labels, Expression *conditions, std::list<Statement *> &stmts, bool isdef = false ) throw(SemanticError);182 CaseStmt( std::list<Label> labels, Expression *conditions, const std::list<Statement *> &stmts, bool isdef = false ) throw(SemanticError); 182 183 CaseStmt( const CaseStmt &other ); 183 184 virtual ~CaseStmt(); … … 194 195 void set_statements( std::list<Statement *> &newValue ) { stmts = newValue; } 195 196 196 virtual void accept( Visitor &v ) { v.visit( this ); }197 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }198 199 virtual CaseStmt *clone() const { return new CaseStmt( *this ); }200 virtual void print( std::ostream &os, int indent = 0 ) const ;197 virtual void accept( Visitor &v ) override { v.visit( this ); } 198 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 199 200 virtual CaseStmt *clone() const override { return new CaseStmt( *this ); } 201 virtual void print( std::ostream &os, int indent = 0 ) const override; 201 202 private: 202 203 bool _isDefault; … … 221 222 void set_isDoWhile( bool newValue ) { isDoWhile = newValue; } 222 223 223 virtual WhileStmt *clone() const { return new WhileStmt( *this ); }224 virtual void accept( Visitor &v ) { v.visit( this ); }225 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }226 virtual void print( std::ostream &os, int indent = 0 ) const ;224 virtual WhileStmt *clone() const override { return new WhileStmt( *this ); } 225 virtual void accept( Visitor &v ) override { v.visit( this ); } 226 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 227 virtual void print( std::ostream &os, int indent = 0 ) const override; 227 228 }; 228 229 … … 247 248 void set_body( Statement *newValue ) { body = newValue; } 248 249 249 virtual ForStmt *clone() const { return new ForStmt( *this ); }250 virtual void accept( Visitor &v ) { v.visit( this ); }251 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }252 virtual void print( std::ostream &os, int indent = 0 ) const ;250 virtual ForStmt *clone() const override { return new ForStmt( *this ); } 251 virtual void accept( Visitor &v ) override { v.visit( this ); } 252 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 253 virtual void print( std::ostream &os, int indent = 0 ) const override; 253 254 }; 254 255 … … 276 277 const char *get_typename() { return brType[ type ]; } 277 278 278 virtual BranchStmt *clone() const { return new BranchStmt( *this ); }279 virtual void accept( Visitor &v ) { v.visit( this ); }280 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }281 virtual void print( std::ostream &os, int indent = 0 ) const ;279 virtual BranchStmt *clone() const override { return new BranchStmt( *this ); } 280 virtual void accept( Visitor &v ) override { v.visit( this ); } 281 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 282 virtual void print( std::ostream &os, int indent = 0 ) const override; 282 283 private: 283 284 static const char *brType[]; … … 295 296 void set_expr( Expression *newValue ) { expr = newValue; } 296 297 297 virtual ReturnStmt *clone() const { return new ReturnStmt( *this ); }298 virtual void accept( Visitor &v ) { v.visit( this ); }299 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }300 virtual void print( std::ostream &os, int indent = 0 ) const ;298 virtual ReturnStmt *clone() const override { return new ReturnStmt( *this ); } 299 virtual void accept( Visitor &v ) override { v.visit( this ); } 300 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 301 virtual void print( std::ostream &os, int indent = 0 ) const override; 301 302 }; 302 303 … … 319 320 void set_target( Expression * newTarget ) { target = newTarget; } 320 321 321 virtual ThrowStmt *clone() const { return new ThrowStmt( *this ); }322 virtual void accept( Visitor &v ) { v.visit( this ); }323 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }324 virtual void print( std::ostream &os, int indent = 0 ) const ;322 virtual ThrowStmt *clone() const override { return new ThrowStmt( *this ); } 323 virtual void accept( Visitor &v ) override { v.visit( this ); } 324 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 325 virtual void print( std::ostream &os, int indent = 0 ) const override; 325 326 }; 326 327 … … 342 343 void set_finally( FinallyStmt *newValue ) { finallyBlock = newValue; } 343 344 344 virtual TryStmt *clone() const { return new TryStmt( *this ); }345 virtual void accept( Visitor &v ) { v.visit( this ); }346 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }347 virtual void print( std::ostream &os, int indent = 0 ) const ;345 virtual TryStmt *clone() const override { return new TryStmt( *this ); } 346 virtual void accept( Visitor &v ) override { v.visit( this ); } 347 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 348 virtual void print( std::ostream &os, int indent = 0 ) const override; 348 349 }; 349 350 … … 370 371 void set_body( Statement *newValue ) { body = newValue; } 371 372 372 virtual CatchStmt *clone() const { return new CatchStmt( *this ); }373 virtual void accept( Visitor &v ) { v.visit( this ); }374 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }375 virtual void print( std::ostream &os, int indent = 0 ) const ;373 virtual CatchStmt *clone() const override { return new CatchStmt( *this ); } 374 virtual void accept( Visitor &v ) override { v.visit( this ); } 375 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 376 virtual void print( std::ostream &os, int indent = 0 ) const override; 376 377 }; 377 378 … … 387 388 void set_block( CompoundStmt *newValue ) { block = newValue; } 388 389 389 virtual FinallyStmt *clone() const { return new FinallyStmt( *this ); }390 virtual void accept( Visitor &v ) { v.visit( this ); }391 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }392 virtual void print( std::ostream &os, int indent = 0 ) const ;390 virtual FinallyStmt *clone() const override { return new FinallyStmt( *this ); } 391 virtual void accept( Visitor &v ) override { v.visit( this ); } 392 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 393 virtual void print( std::ostream &os, int indent = 0 ) const override; 393 394 }; 394 395 … … 424 425 } orelse; 425 426 426 virtual WaitForStmt *clone() const { return new WaitForStmt( *this ); }427 virtual void accept( Visitor &v ) { v.visit( this ); }428 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }429 virtual void print( std::ostream &os, int indent = 0 ) const ;427 virtual WaitForStmt *clone() const override { return new WaitForStmt( *this ); } 428 virtual void accept( Visitor &v ) override { v.visit( this ); } 429 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 430 virtual void print( std::ostream &os, int indent = 0 ) const override; 430 431 431 432 }; … … 444 445 void set_decl( Declaration *newValue ) { decl = newValue; } 445 446 446 virtual DeclStmt *clone() const { return new DeclStmt( *this ); }447 virtual void accept( Visitor &v ) { v.visit( this ); }448 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }449 virtual void print( std::ostream &os, int indent = 0 ) const ;447 virtual DeclStmt *clone() const override { return new DeclStmt( *this ); } 448 virtual void accept( Visitor &v ) override { v.visit( this ); } 449 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 450 virtual void print( std::ostream &os, int indent = 0 ) const override; 450 451 }; 451 452 … … 466 467 void set_callStmt( Statement * newValue ) { callStmt = newValue; } 467 468 468 virtual ImplicitCtorDtorStmt *clone() const { return new ImplicitCtorDtorStmt( *this ); } 469 virtual void accept( Visitor &v ) { v.visit( this ); } 470 virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); } 471 virtual void print( std::ostream &os, int indent = 0 ) const; 472 }; 473 474 475 std::ostream & operator<<( std::ostream & out, const Statement * statement ); 469 virtual ImplicitCtorDtorStmt *clone() const override { return new ImplicitCtorDtorStmt( *this ); } 470 virtual void accept( Visitor &v ) override { v.visit( this ); } 471 virtual Statement *acceptMutator( Mutator &m ) override { return m.mutate( this ); } 472 virtual void print( std::ostream &os, int indent = 0 ) const override; 473 }; 476 474 477 475 // Local Variables: // -
src/SynTree/Type.cc
r201aeb9 rd67cdb7 101 101 const Type::Qualifiers noQualifiers; 102 102 103 std::ostream & operator<<( std::ostream & out, const Type * type ) {104 if ( type ) {105 type->print( out );106 } else {107 out << "nullptr";108 } // if109 return out;110 }111 112 103 // Local Variables: // 113 104 // tab-width: 4 // -
src/SynTree/Type.h
r201aeb9 rd67cdb7 192 192 VoidType( const Type::Qualifiers & tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 193 193 194 virtual unsigned size() const { return 0; };195 virtual bool isComplete() const { return false; }196 197 virtual VoidType *clone() const { return new VoidType( *this ); }198 virtual void accept( Visitor & v ) { v.visit( this ); }199 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }200 virtual void print( std::ostream & os, int indent = 0 ) const ;194 virtual unsigned size() const override { return 0; }; 195 virtual bool isComplete() const override { return false; } 196 197 virtual VoidType *clone() const override { return new VoidType( *this ); } 198 virtual void accept( Visitor & v ) override { v.visit( this ); } 199 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 200 virtual void print( std::ostream & os, int indent = 0 ) const override; 201 201 }; 202 202 … … 237 237 void set_kind( Kind newValue ) { kind = newValue; } 238 238 239 virtual BasicType *clone() const { return new BasicType( *this ); }240 virtual void accept( Visitor & v ) { v.visit( this ); }241 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }242 virtual void print( std::ostream & os, int indent = 0 ) const ;239 virtual BasicType *clone() const override { return new BasicType( *this ); } 240 virtual void accept( Visitor & v ) override { v.visit( this ); } 241 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 242 virtual void print( std::ostream & os, int indent = 0 ) const override; 243 243 244 244 bool isInteger() const; … … 270 270 bool is_array() const { return isStatic || isVarLen || dimension; } 271 271 272 virtual bool isComplete() const { return ! isVarLen; }273 274 virtual PointerType *clone() const { return new PointerType( *this ); }275 virtual void accept( Visitor & v ) { v.visit( this ); }276 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }277 virtual void print( std::ostream & os, int indent = 0 ) const ;272 virtual bool isComplete() const override { return ! isVarLen; } 273 274 virtual PointerType *clone() const override { return new PointerType( *this ); } 275 virtual void accept( Visitor & v ) override { v.visit( this ); } 276 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 277 virtual void print( std::ostream & os, int indent = 0 ) const override; 278 278 }; 279 279 … … 298 298 void set_isStatic( bool newValue ) { isStatic = newValue; } 299 299 300 virtual bool isComplete() const { return ! isVarLen; }301 302 virtual ArrayType *clone() const { return new ArrayType( *this ); }303 virtual void accept( Visitor & v ) { v.visit( this ); }304 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }305 virtual void print( std::ostream & os, int indent = 0 ) const ;300 virtual bool isComplete() const override { return ! isVarLen; } 301 302 virtual ArrayType *clone() const override { return new ArrayType( *this ); } 303 virtual void accept( Visitor & v ) override { v.visit( this ); } 304 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 305 virtual void print( std::ostream & os, int indent = 0 ) const override; 306 306 }; 307 307 … … 317 317 void set_base( Type *newValue ) { base = newValue; } 318 318 319 virtual int referenceDepth() const ;319 virtual int referenceDepth() const override; 320 320 321 321 // Since reference types act like value types, their size is the size of the base. 322 322 // This makes it simple to cast the empty tuple to a reference type, since casts that increase 323 323 // the number of values are disallowed. 324 virtual unsigned size() const { return base->size(); }325 326 virtual ReferenceType *clone() const { return new ReferenceType( *this ); }327 virtual void accept( Visitor & v ) { v.visit( this ); }328 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }329 virtual void print( std::ostream & os, int indent = 0 ) const ;324 virtual unsigned size() const override { return base->size(); } 325 326 virtual ReferenceType *clone() const override { return new ReferenceType( *this ); } 327 virtual void accept( Visitor & v ) override { v.visit( this ); } 328 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 329 virtual void print( std::ostream & os, int indent = 0 ) const override; 330 330 }; 331 331 … … 351 351 bool isTtype() const; 352 352 353 virtual FunctionType *clone() const { return new FunctionType( *this ); }354 virtual void accept( Visitor & v ) { v.visit( this ); }355 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }356 virtual void print( std::ostream & os, int indent = 0 ) const ;353 virtual FunctionType *clone() const override { return new FunctionType( *this ); } 354 virtual void accept( Visitor & v ) override { v.visit( this ); } 355 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 356 virtual void print( std::ostream & os, int indent = 0 ) const override; 357 357 }; 358 358 … … 373 373 void set_hoistType( bool newValue ) { hoistType = newValue; } 374 374 375 virtual ReferenceToType *clone() const = 0;376 virtual void accept( Visitor & v ) = 0;377 virtual Type *acceptMutator( Mutator & m ) = 0;378 virtual void print( std::ostream & os, int indent = 0 ) const ;375 virtual ReferenceToType *clone() const override = 0; 376 virtual void accept( Visitor & v ) override = 0; 377 virtual Type *acceptMutator( Mutator & m ) override = 0; 378 virtual void print( std::ostream & os, int indent = 0 ) const override; 379 379 380 380 virtual void lookup( __attribute__((unused)) const std::string & name, __attribute__((unused)) std::list< Declaration* > & foundDecls ) const {} … … 400 400 std::list<TypeDecl*> * get_baseParameters(); 401 401 402 virtual bool isComplete() const ;402 virtual bool isComplete() const override; 403 403 404 404 /// Looks up the members of this struct named "name" and places them into "foundDecls". 405 405 /// Clones declarations into "foundDecls", caller responsible for freeing 406 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const ;407 408 virtual StructInstType *clone() const { return new StructInstType( *this ); }409 virtual void accept( Visitor & v ) { v.visit( this ); }410 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }411 412 virtual void print( std::ostream & os, int indent = 0 ) const ;406 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 407 408 virtual StructInstType *clone() const override { return new StructInstType( *this ); } 409 virtual void accept( Visitor & v ) override { v.visit( this ); } 410 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 411 412 virtual void print( std::ostream & os, int indent = 0 ) const override; 413 413 private: 414 virtual std::string typeString() const ;414 virtual std::string typeString() const override; 415 415 }; 416 416 … … 432 432 std::list< TypeDecl * > * get_baseParameters(); 433 433 434 virtual bool isComplete() const ;434 virtual bool isComplete() const override; 435 435 436 436 /// looks up the members of this union named "name" and places them into "foundDecls" 437 437 /// Clones declarations into "foundDecls", caller responsible for freeing 438 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const ;439 440 virtual UnionInstType *clone() const { return new UnionInstType( *this ); }441 virtual void accept( Visitor & v ) { v.visit( this ); }442 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }443 444 virtual void print( std::ostream & os, int indent = 0 ) const ;438 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 439 440 virtual UnionInstType *clone() const override { return new UnionInstType( *this ); } 441 virtual void accept( Visitor & v ) override { v.visit( this ); } 442 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 443 444 virtual void print( std::ostream & os, int indent = 0 ) const override; 445 445 private: 446 virtual std::string typeString() const ;446 virtual std::string typeString() const override; 447 447 }; 448 448 … … 461 461 void set_baseEnum( EnumDecl *newValue ) { baseEnum = newValue; } 462 462 463 virtual bool isComplete() const ;464 465 virtual EnumInstType *clone() const { return new EnumInstType( *this ); }466 virtual void accept( Visitor & v ) { v.visit( this ); }467 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }463 virtual bool isComplete() const override; 464 465 virtual EnumInstType *clone() const override { return new EnumInstType( *this ); } 466 virtual void accept( Visitor & v ) override { v.visit( this ); } 467 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 468 468 private: 469 virtual std::string typeString() const ;469 virtual std::string typeString() const override; 470 470 }; 471 471 … … 482 482 ~TraitInstType(); 483 483 484 virtual bool isComplete() const ;485 486 virtual TraitInstType *clone() const { return new TraitInstType( *this ); }487 virtual void accept( Visitor & v ) { v.visit( this ); }488 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }484 virtual bool isComplete() const override; 485 486 virtual TraitInstType *clone() const override { return new TraitInstType( *this ); } 487 virtual void accept( Visitor & v ) override { v.visit( this ); } 488 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 489 489 private: 490 virtual std::string typeString() const ;490 virtual std::string typeString() const override; 491 491 }; 492 492 … … 509 509 void set_isFtype( bool newValue ) { isFtype = newValue; } 510 510 511 virtual bool isComplete() const ;512 513 virtual TypeInstType *clone() const { return new TypeInstType( *this ); }514 virtual void accept( Visitor & v ) { v.visit( this ); }515 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }516 virtual void print( std::ostream & os, int indent = 0 ) const ;511 virtual bool isComplete() const override; 512 513 virtual TypeInstType *clone() const override { return new TypeInstType( *this ); } 514 virtual void accept( Visitor & v ) override { v.visit( this ); } 515 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 516 virtual void print( std::ostream & os, int indent = 0 ) const override; 517 517 private: 518 virtual std::string typeString() const ;518 virtual std::string typeString() const override; 519 519 }; 520 520 … … 532 532 533 533 std::list<Type *> & get_types() { return types; } 534 virtual unsigned size() const { return types.size(); };534 virtual unsigned size() const override { return types.size(); }; 535 535 536 536 // For now, this is entirely synthetic -- tuple types always have unnamed members. … … 541 541 iterator end() { return types.end(); } 542 542 543 virtual Type * getComponent( unsigned i ) {543 virtual Type * getComponent( unsigned i ) override { 544 544 assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", i, size() ); 545 545 return *(begin()+i); 546 546 } 547 547 548 // virtual bool isComplete() const { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness549 550 virtual TupleType *clone() const { return new TupleType( *this ); }551 virtual void accept( Visitor & v ) { v.visit( this ); }552 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }553 virtual void print( std::ostream & os, int indent = 0 ) const ;548 // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness 549 550 virtual TupleType *clone() const override { return new TupleType( *this ); } 551 virtual void accept( Visitor & v ) override { v.visit( this ); } 552 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 553 virtual void print( std::ostream & os, int indent = 0 ) const override; 554 554 }; 555 555 … … 565 565 void set_expr( Expression *newValue ) { expr = newValue; } 566 566 567 virtual bool isComplete() const { assert( false ); return false; }568 569 virtual TypeofType *clone() const { return new TypeofType( *this ); }570 virtual void accept( Visitor & v ) { v.visit( this ); }571 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }572 virtual void print( std::ostream & os, int indent = 0 ) const ;567 virtual bool isComplete() const override { assert( false ); return false; } 568 569 virtual TypeofType *clone() const override { return new TypeofType( *this ); } 570 virtual void accept( Visitor & v ) override { v.visit( this ); } 571 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 572 virtual void print( std::ostream & os, int indent = 0 ) const override; 573 573 }; 574 574 … … 594 594 void set_isType( bool newValue ) { isType = newValue; } 595 595 596 virtual bool isComplete() const { assert( false ); } // xxx - not sure what to do here597 598 virtual AttrType *clone() const { return new AttrType( *this ); }599 virtual void accept( Visitor & v ) { v.visit( this ); }600 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }601 virtual void print( std::ostream & os, int indent = 0 ) const ;596 virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here 597 598 virtual AttrType *clone() const override { return new AttrType( *this ); } 599 virtual void accept( Visitor & v ) override { v.visit( this ); } 600 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 601 virtual void print( std::ostream & os, int indent = 0 ) const override; 602 602 }; 603 603 … … 608 608 VarArgsType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 609 609 610 virtual bool isComplete() const { return true; } // xxx - is this right?611 612 virtual VarArgsType *clone() const { return new VarArgsType( *this ); }613 virtual void accept( Visitor & v ) { v.visit( this ); }614 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }615 virtual void print( std::ostream & os, int indent = 0 ) const ;610 virtual bool isComplete() const override{ return true; } // xxx - is this right? 611 612 virtual VarArgsType *clone() const override { return new VarArgsType( *this ); } 613 virtual void accept( Visitor & v ) override { v.visit( this ); } 614 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 615 virtual void print( std::ostream & os, int indent = 0 ) const override; 616 616 }; 617 617 … … 622 622 ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 623 623 624 virtual ZeroType *clone() const { return new ZeroType( *this ); }625 virtual void accept( Visitor & v ) { v.visit( this ); }626 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); }627 virtual void print( std::ostream & os, int indent = 0 ) const ;624 virtual ZeroType *clone() const override { return new ZeroType( *this ); } 625 virtual void accept( Visitor & v ) override { v.visit( this ); } 626 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 627 virtual void print( std::ostream & os, int indent = 0 ) const override; 628 628 }; 629 629 … … 634 634 OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 635 635 636 virtual OneType *clone() const { return new OneType( *this ); } 637 virtual void accept( Visitor & v ) { v.visit( this ); } 638 virtual Type *acceptMutator( Mutator & m ) { return m.mutate( this ); } 639 virtual void print( std::ostream & os, int indent = 0 ) const; 640 }; 641 642 std::ostream & operator<<( std::ostream & out, const Type * type ); 636 virtual OneType *clone() const override { return new OneType( *this ); } 637 virtual void accept( Visitor & v ) override { v.visit( this ); } 638 virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); } 639 virtual void print( std::ostream & os, int indent = 0 ) const override; 640 }; 643 641 644 642 // Local Variables: // -
src/SynTree/Visitor.h
r201aeb9 rd67cdb7 25 25 public: 26 26 // visit: Default implementation of all functions visits the children 27 27 // of the given syntax node, but performs no other action. 28 28 29 29 virtual void visit( ObjectDecl *objectDecl ); -
src/SynTree/module.mk
r201aeb9 rd67cdb7 48 48 SynTree/Visitor.cc \ 49 49 SynTree/Mutator.cc \ 50 SynTree/AddStmtVisitor.cc \51 50 SynTree/TypeSubstitution.cc \ 52 51 SynTree/Attribute.cc \ -
src/Tuples/TupleExpansion.cc
r201aeb9 rd67cdb7 21 21 #include "Common/ScopedMap.h" // for ScopedMap 22 22 #include "Common/utility.h" // for CodeLocation 23 #include "GenPoly/DeclMutator.h" // for DeclMutator24 23 #include "InitTweak/InitTweak.h" // for getFunction 25 24 #include "Parser/LinkageSpec.h" // for Spec, C, Intrinsic -
src/benchmark/Makefile.am
r201aeb9 rd67cdb7 48 48 @rm -f a.out .result.log 49 49 50 ctxswitch-pthread$(EXEEXT): 51 @BACKEND_CC@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} -lrt -pthread -DN=50000000 PthrdCtxSwitch.c 52 @rm -f .result.log 53 @for number in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do \ 54 ./a.out | tee -a .result.log ; \ 55 done 56 @./stat.py .result.log 57 @rm -f a.out .result.log 58 50 59 sched-int$(EXEEXT): 51 60 ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=50000000 SchedInt.c -
src/benchmark/Makefile.in
r201aeb9 rd67cdb7 598 598 @rm -f a.out .result.log 599 599 600 ctxswitch-pthread$(EXEEXT): 601 @BACKEND_CC@ ${AM_CFLAGS} ${CFLAGS} ${ccflags} -lrt -pthread -DN=50000000 PthrdCtxSwitch.c 602 @rm -f .result.log 603 @for number in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do \ 604 ./a.out | tee -a .result.log ; \ 605 done 606 @./stat.py .result.log 607 @rm -f a.out .result.log 608 600 609 sched-int$(EXEEXT): 601 610 ${CC} ${AM_CFLAGS} ${CFLAGS} ${ccflags} @CFA_FLAGS@ -nodebug -lrt -DN=50000000 SchedInt.c -
src/benchmark/bench.h
r201aeb9 rd67cdb7 1 1 #pragma once 2 2 3 #ifdef __CFORALL__ 3 4 extern "C" { 5 #endif 4 6 #include <unistd.h> // sysconf 5 7 #include <sys/times.h> // times 6 8 #include <time.h> 9 #ifdef __CFORALL__ 7 10 } 11 #endif 8 12 9 inline unsigned long long int Time() {10 timespec ts;13 static inline unsigned long long int Time() { 14 struct timespec ts; 11 15 clock_gettime( 12 16 #if defined( __linux__ ) -
src/benchmark/create_cfaThrd.c
r201aeb9 rd67cdb7 4 4 5 5 thread MyThread {}; 6 void main(MyThread *this) {}6 void main(MyThread & this) {} 7 7 8 8 int main(int argc, char* argv[]) { -
src/libcfa/Makefile.am
r201aeb9 rd67cdb7 36 36 ${AM_V_GEN}@BACKEND_CC@ @CFA_FLAGS@ -D__CFA_DEBUG__ -O0 -c -o $@ $< 37 37 38 EXTRA_FLAGS = -g -Wall -W error -Wno-unused-function -imacros libcfa-prelude.c @CFA_FLAGS@38 EXTRA_FLAGS = -g -Wall -Wno-unused-function -imacros libcfa-prelude.c @CFA_FLAGS@ 39 39 40 40 AM_CCASFLAGS = @CFA_FLAGS@ -
src/libcfa/Makefile.in
r201aeb9 rd67cdb7 416 416 ARFLAGS = cr 417 417 lib_LIBRARIES = $(am__append_1) $(am__append_2) 418 EXTRA_FLAGS = -g -Wall -W error -Wno-unused-function -imacros libcfa-prelude.c @CFA_FLAGS@418 EXTRA_FLAGS = -g -Wall -Wno-unused-function -imacros libcfa-prelude.c @CFA_FLAGS@ 419 419 AM_CCASFLAGS = @CFA_FLAGS@ 420 420 headers = fstream iostream iterator limits rational stdlib \ -
src/libcfa/concurrency/coroutine.c
r201aeb9 rd67cdb7 123 123 if(pageSize == 0ul) pageSize = sysconf( _SC_PAGESIZE ); 124 124 125 LIB_DEBUG_PRINT_SAFE("FRED");126 127 125 size_t cxtSize = libCeiling( sizeof(machine_context_t), 8 ); // minimum alignment 128 126 -
src/libcfa/concurrency/invoke.h
r201aeb9 rd67cdb7 84 84 }; 85 85 86 struct __waitfor_mask_t { 87 short * accepted; // the index of the accepted function, -1 if none 88 struct __acceptable_t * clauses; // list of acceptable functions, null if any 89 short size; // number of acceptable functions 90 }; 91 86 92 struct monitor_desc { 87 93 struct spinlock lock; // spinlock to protect internal data … … 90 96 struct __condition_stack_t signal_stack; // stack of conditions to run next once we exit the monitor 91 97 unsigned int recursion; // monitor routines can be called recursively, we need to keep track of that 98 struct __waitfor_mask_t mask; // mask used to know if some thread is waiting for something while holding the monitor 99 }; 92 100 93 struct __acceptable_t * acceptables; // list of acceptable functions, null if any 94 unsigned short acceptable_count; // number of acceptable functions 95 short accepted_index; // the index of the accepted function, -1 if none 96 }; 101 struct __monitor_group_t { 102 struct monitor_desc ** list; // currently held monitors 103 short size; // number of currently held monitors 104 fptr_t func; // last function that acquired monitors 105 }; 97 106 98 107 struct thread_desc { 99 108 // Core threading fields 100 struct coroutine_desc cor; // coroutine body used to store context 101 struct monitor_desc mon; // monitor body used for mutual exclusion 109 struct coroutine_desc self_cor; // coroutine body used to store context 110 struct monitor_desc self_mon; // monitor body used for mutual exclusion 111 struct monitor_desc * self_mon_p; // pointer to monitor with sufficient lifetime for current monitors 112 struct __monitor_group_t monitors; // monitors currently held by this thread 102 113 103 114 // Link lists fields 104 115 struct thread_desc * next; // instrusive link field for threads 105 116 106 // Current status related to monitors 107 struct monitor_desc ** current_monitors; // currently held monitors 108 unsigned short current_monitor_count; // number of currently held monitors 109 fptr_t current_monitor_func; // last function that acquired monitors 117 110 118 }; 119 120 #ifdef __CFORALL__ 121 extern "Cforall" { 122 static inline monitor_desc * ?[?]( const __monitor_group_t & this, ptrdiff_t index ) { 123 return this.list[index]; 124 } 125 126 static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) { 127 if( (lhs.list != 0) != (rhs.list != 0) ) return false; 128 if( lhs.size != rhs.size ) return false; 129 if( lhs.func != rhs.func ) return false; 130 131 // Check that all the monitors match 132 for( int i = 0; i < lhs.size; i++ ) { 133 // If not a match, check next function 134 if( lhs[i] != rhs[i] ) return false; 135 } 136 137 return true; 138 } 139 } 140 #endif 111 141 112 142 #endif //_INVOKE_H_ -
src/libcfa/concurrency/kernel.c
r201aeb9 rd67cdb7 106 106 107 107 void ?{}( thread_desc & this, current_stack_info_t * info) { 108 (this. cor){ info };108 (this.self_cor){ info }; 109 109 } 110 110 … … 328 328 // if( !thrd ) return; 329 329 verify( thrd ); 330 verify( thrd-> cor.state != Halted );330 verify( thrd->self_cor.state != Halted ); 331 331 332 332 verify( disable_preempt_count > 0 ); … … 373 373 assert(thrd); 374 374 disable_interrupts(); 375 assert( thrd-> cor.state != Halted );375 assert( thrd->self_cor.state != Halted ); 376 376 this_processor->finish.action_code = Schedule; 377 377 this_processor->finish.thrd = thrd; … … 466 466 this_processor = mainProcessor; 467 467 this_thread = mainThread; 468 this_coroutine = &mainThread-> cor;468 this_coroutine = &mainThread->self_cor; 469 469 470 470 // Enable preemption … … 547 547 thread_desc * thrd = kernel_data; 548 548 549 int len = snprintf( abort_text, abort_text_size, "Error occurred while executing task %.256s (%p)", thrd-> cor.name, thrd );549 int len = snprintf( abort_text, abort_text_size, "Error occurred while executing task %.256s (%p)", thrd->self_cor.name, thrd ); 550 550 __lib_debug_write( STDERR_FILENO, abort_text, len ); 551 551 -
src/libcfa/concurrency/monitor
r201aeb9 rd67cdb7 22 22 #include "stdlib" 23 23 24 trait is_monitor(dtype T) { 25 monitor_desc * get_monitor( T & ); 26 void ^?{}( T & mutex ); 27 }; 28 24 29 static inline void ?{}(monitor_desc & this) { 25 30 (this.lock){}; … … 28 33 (this.signal_stack){}; 29 34 this.recursion = 0; 30 this. acceptables= NULL;31 this. acceptable_count = 0;32 this. accepted_index = -1;35 this.mask.accepted = NULL; 36 this.mask.clauses = NULL; 37 this.mask.size = 0; 33 38 } 34 39 … … 100 105 101 106 struct __acceptable_t { 102 fptr_t func; 103 unsigned short count; 104 monitor_desc ** monitors; 107 __monitor_group_t; 105 108 bool is_dtor; 106 109 }; 107 110 108 int __accept_internal( unsigned short count, __acceptable_t * acceptables);111 void __waitfor_internal( const __waitfor_mask_t & mask, int duration ); 109 112 110 113 // Local Variables: // -
src/libcfa/concurrency/monitor.c
r201aeb9 rd67cdb7 23 23 //----------------------------------------------------------------------------- 24 24 // Forward declarations 25 static inline void set_owner( monitor_desc * this, thread_desc * owner ); 25 static inline void set_owner ( monitor_desc * this, thread_desc * owner ); 26 static inline void set_owner ( monitor_desc ** storage, short count, thread_desc * owner ); 27 static inline void set_mask ( monitor_desc ** storage, short count, const __waitfor_mask_t & mask ); 28 static inline void reset_mask( monitor_desc * this ); 29 26 30 static inline thread_desc * next_thread( monitor_desc * this ); 27 static inline int is_accepted( thread_desc * owner, monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)());31 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & monitors ); 28 32 29 33 static inline void lock_all( spinlock ** locks, unsigned short count ); … … 32 36 static inline void unlock_all( monitor_desc ** locks, unsigned short count ); 33 37 34 static inline void save _recursion ( monitor_desc ** ctx, unsigned int * /*out*/ recursions, unsigned short count);35 static inline void restore _recursion( monitor_desc ** ctx, unsigned int * /*in */ recursions, unsigned short count);38 static inline void save ( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ); 39 static inline void restore( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*in */ recursions, __waitfor_mask_t * /*in */ masks ); 36 40 37 41 static inline void init ( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 38 42 static inline void init_push( int count, monitor_desc ** monitors, __condition_node_t * waiter, __condition_criterion_t * criteria ); 39 43 40 static inline thread_desc * check_condition( __condition_criterion_t * ); 41 static inline void brand_condition( condition * ); 42 static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val ); 43 44 static inline thread_desc * search_entry_queue( __acceptable_t * acceptables, int acc_count, monitor_desc ** monitors, int count ); 44 static inline thread_desc * check_condition ( __condition_criterion_t * ); 45 static inline void brand_condition ( condition * ); 46 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc ** monitors, int count ); 47 48 forall(dtype T | sized( T )) 49 static inline short insert_unique( T ** array, short & size, T * val ); 50 static inline short count_max ( const __waitfor_mask_t & mask ); 51 static inline short aggregate ( monitor_desc ** storage, const __waitfor_mask_t & mask ); 45 52 46 53 //----------------------------------------------------------------------------- 47 54 // Useful defines 48 #define wait_ctx(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 49 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 50 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 51 init( count, monitors, &waiter, criteria ); /* Link everything together */ \ 52 53 #define wait_ctx_primed(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 54 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 55 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 56 init_push( count, monitors, &waiter, criteria ); /* Link everything together and push it to the AS-Stack */ \ 57 58 #define monitor_ctx( mons, cnt ) /* Define that create the necessary struct for internal/external scheduling operations */ \ 59 monitor_desc ** monitors = mons; /* Save the targeted monitors */ \ 60 unsigned short count = cnt; /* Save the count to a local variable */ \ 61 unsigned int recursions[ count ]; /* Save the current recursion levels to restore them later */ \ 62 spinlock * locks [ count ]; /* We need to pass-in an array of locks to BlockInternal */ \ 55 #define wait_ctx(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 56 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 57 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 58 init( count, monitors, &waiter, criteria ); /* Link everything together */ \ 59 60 #define wait_ctx_primed(thrd, user_info) /* Create the necessary information to use the signaller stack */ \ 61 __condition_node_t waiter = { thrd, count, user_info }; /* Create the node specific to this wait operation */ \ 62 __condition_criterion_t criteria[count]; /* Create the creteria this wait operation needs to wake up */ \ 63 init_push( count, monitors, &waiter, criteria ); /* Link everything together and push it to the AS-Stack */ \ 64 65 #define monitor_ctx( mons, cnt ) /* Define that create the necessary struct for internal/external scheduling operations */ \ 66 monitor_desc ** monitors = mons; /* Save the targeted monitors */ \ 67 unsigned short count = cnt; /* Save the count to a local variable */ \ 68 unsigned int recursions[ count ]; /* Save the current recursion levels to restore them later */ \ 69 __waitfor_mask_t masks[ count ]; /* Save the current waitfor masks to restore them later */ \ 70 spinlock * locks [ count ]; /* We need to pass-in an array of locks to BlockInternal */ \ 71 72 #define monitor_save save ( monitors, count, locks, recursions, masks ) 73 #define monitor_restore restore( monitors, count, locks, recursions, masks ) 74 63 75 64 76 //----------------------------------------------------------------------------- … … 68 80 extern "C" { 69 81 // Enter single monitor 70 static void __enter_monitor_desc( monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)()) {82 static void __enter_monitor_desc( monitor_desc * this, const __monitor_group_t & group ) { 71 83 // Lock the monitor spinlock, lock_yield to reduce contention 72 84 lock_yield( &this->lock DEBUG_CTX2 ); … … 75 87 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner); 76 88 77 this->accepted_index = -1;78 89 if( !this->owner ) { 79 90 // No one has the monitor, just take it … … 89 100 LIB_DEBUG_PRINT_SAFE("Kernel : mon already owned \n"); 90 101 } 91 else if( (this->accepted_index = is_accepted( thrd, this, group, group_cnt, func)) >= 0) {102 else if( is_accepted( this, group) ) { 92 103 // Some one was waiting for us, enter 93 104 set_owner( this, thrd ); 105 106 // Reset mask 107 reset_mask( this ); 94 108 95 109 LIB_DEBUG_PRINT_SAFE("Kernel : mon accepts \n"); … … 120 134 lock_yield( &this->lock DEBUG_CTX2 ); 121 135 122 verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i)", this_thread, this->owner, this->recursion ); 136 LIB_DEBUG_PRINT_SAFE("Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner); 137 138 verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", this_thread, this->owner, this->recursion, this ); 123 139 124 140 // Leaving a recursion level, decrement the counter … … 146 162 // Should never return 147 163 void __leave_thread_monitor( thread_desc * thrd ) { 148 monitor_desc * this = &thrd-> mon;164 monitor_desc * this = &thrd->self_mon; 149 165 150 166 // Lock the monitor now … … 153 169 disable_interrupts(); 154 170 155 thrd-> cor.state = Halted;156 157 verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i )", thrd, this->owner, this->recursion);171 thrd->self_cor.state = Halted; 172 173 verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this ); 158 174 159 175 // Leaving a recursion level, decrement the counter … … 178 194 // Enter multiple monitor 179 195 // relies on the monitor array being sorted 180 static inline void enter( monitor_desc ** monitors, int count, void (*func)()) {181 for(int i = 0; i < count; i++) {182 __enter_monitor_desc( monitors [i], monitors, count, func);196 static inline void enter( __monitor_group_t monitors ) { 197 for(int i = 0; i < monitors.size; i++) { 198 __enter_monitor_desc( monitors.list[i], monitors ); 183 199 } 184 200 } … … 203 219 204 220 // Save previous thread context 205 this.prev_mntrs = this_thread-> current_monitors;206 this.prev_count = this_thread-> current_monitor_count;207 this.prev_func = this_thread-> current_monitor_func;221 this.prev_mntrs = this_thread->monitors.list; 222 this.prev_count = this_thread->monitors.size; 223 this.prev_func = this_thread->monitors.func; 208 224 209 225 // Update thread context (needed for conditions) 210 this_thread->current_monitors = m; 211 this_thread->current_monitor_count = count; 212 this_thread->current_monitor_func = func; 226 this_thread->monitors.list = m; 227 this_thread->monitors.size = count; 228 this_thread->monitors.func = func; 229 230 // LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count); 213 231 214 232 // Enter the monitors in order 215 enter( this.m, this.count, func ); 233 __monitor_group_t group = {this.m, this.count, func}; 234 enter( group ); 235 236 // LIB_DEBUG_PRINT_SAFE("MGUARD : entered\n"); 216 237 } 217 238 … … 219 240 // Dtor for monitor guard 220 241 void ^?{}( monitor_guard_t & this ) { 242 // LIB_DEBUG_PRINT_SAFE("MGUARD : leaving %d\n", this.count); 243 221 244 // Leave the monitors in order 222 245 leave( this.m, this.count ); 223 246 247 // LIB_DEBUG_PRINT_SAFE("MGUARD : left\n"); 248 224 249 // Restore thread context 225 this_thread-> current_monitors= this.prev_mntrs;226 this_thread-> current_monitor_count= this.prev_count;227 this_thread-> current_monitor_func= this.prev_func;250 this_thread->monitors.list = this.prev_mntrs; 251 this_thread->monitors.size = this.prev_count; 252 this_thread->monitors.func = this.prev_func; 228 253 } 229 254 … … 271 296 append( &this->blocked, &waiter ); 272 297 273 // Lock all monitors (aggregates the lock themas well)298 // Lock all monitors (aggregates the locks as well) 274 299 lock_all( monitors, locks, count ); 275 300 276 // DON'T unlock, ask the kernel to do it277 278 // Save monitor state279 save_recursion( monitors, recursions, count );280 281 301 // Find the next thread(s) to run 282 unsignedshort thread_count = 0;302 short thread_count = 0; 283 303 thread_desc * threads[ count ]; 284 304 for(int i = 0; i < count; i++) { … … 286 306 } 287 307 308 // Save monitor states 309 monitor_save; 310 288 311 // Remove any duplicate threads 289 312 for( int i = 0; i < count; i++) { 290 313 thread_desc * new_owner = next_thread( monitors[i] ); 291 thread_count =insert_unique( threads, thread_count, new_owner );314 insert_unique( threads, thread_count, new_owner ); 292 315 } 293 316 … … 295 318 BlockInternal( locks, count, threads, thread_count ); 296 319 297 298 // WE WOKE UP299 300 301 320 // We are back, restore the owners and recursions 302 lock_all( locks, count ); 303 restore_recursion( monitors, recursions, count ); 304 unlock_all( locks, count ); 321 monitor_restore; 305 322 } 306 323 … … 315 332 LIB_DEBUG_DO( 316 333 thread_desc * this_thrd = this_thread; 317 if ( this->monitor_count != this_thrd-> current_monitor_count) {318 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd-> current_monitor_count);334 if ( this->monitor_count != this_thrd->monitors.size ) { 335 abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", this, this->monitor_count, this_thrd->monitors.size ); 319 336 } 320 337 321 338 for(int i = 0; i < this->monitor_count; i++) { 322 if ( this->monitors[i] != this_thrd-> current_monitors[i] ) {323 abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd-> current_monitors[i] );339 if ( this->monitors[i] != this_thrd->monitors.list[i] ) { 340 abortf( "Signal on condition %p made with different monitor, expected %p got %i", this, this->monitors[i], this_thrd->monitors.list[i] ); 324 341 } 325 342 } … … 364 381 365 382 //save contexts 366 save_recursion( monitors, recursions, count );383 monitor_save; 367 384 368 385 //Find the thread to run 369 386 thread_desc * signallee = pop_head( &this->blocked )->waiting_thread; 370 for(int i = 0; i < count; i++) { 371 set_owner( monitors[i], signallee ); 372 } 387 set_owner( monitors, count, signallee ); 373 388 374 389 //Everything is ready to go to sleep … … 379 394 380 395 381 //We are back, restore the owners and recursions 382 lock_all( locks, count ); 383 restore_recursion( monitors, recursions, count ); 384 unlock_all( locks, count ); 396 //We are back, restore the masks and recursions 397 monitor_restore; 385 398 386 399 return true; … … 397 410 398 411 //----------------------------------------------------------------------------- 399 // Internal scheduling 400 int __accept_internal( unsigned short acc_count, __acceptable_t * acceptables ) { 401 thread_desc * thrd = this_thread; 412 // External scheduling 413 // cases to handle : 414 // - target already there : 415 // block and wake 416 // - dtor already there 417 // put thread on signaller stack 418 // - non-blocking 419 // return else 420 // - timeout 421 // return timeout 422 // - block 423 // setup mask 424 // block 425 void __waitfor_internal( const __waitfor_mask_t & mask, int duration ) { 426 // This statment doesn't have a contiguous list of monitors... 427 // Create one! 428 short max = count_max( mask ); 429 monitor_desc * mon_storage[max]; 430 short actual_count = aggregate( mon_storage, mask ); 431 432 if(actual_count == 0) return; 433 434 LIB_DEBUG_PRINT_SAFE("Kernel : waitfor internal proceeding\n"); 402 435 403 436 // Create storage for monitor context 404 monitor_ctx( acceptables->monitors, acceptables->count );405 406 // Lock all monitors (aggregates the lock themas well)437 monitor_ctx( mon_storage, actual_count ); 438 439 // Lock all monitors (aggregates the locks as well) 407 440 lock_all( monitors, locks, count ); 408 441 442 { 443 // Check if the entry queue 444 thread_desc * next; int index; 445 [next, index] = search_entry_queue( mask, monitors, count ); 446 447 if( next ) { 448 *mask.accepted = index; 449 if( mask.clauses[index].is_dtor ) { 450 #warning case not implemented 451 } 452 else { 453 LIB_DEBUG_PRINT_SAFE("Kernel : thread present, baton-passing\n"); 454 455 // Create the node specific to this wait operation 456 wait_ctx_primed( this_thread, 0 ); 457 458 // Save monitor states 459 monitor_save; 460 461 // Set the owners to be the next thread 462 set_owner( monitors, count, next ); 463 464 // Everything is ready to go to sleep 465 BlockInternal( locks, count, &next, 1 ); 466 467 // We are back, restore the owners and recursions 468 monitor_restore; 469 470 LIB_DEBUG_PRINT_SAFE("Kernel : thread present, returned\n"); 471 } 472 473 LIB_DEBUG_PRINT_SAFE("Kernel : accepted %d\n", *mask.accepted); 474 475 return; 476 } 477 } 478 479 480 if( duration == 0 ) { 481 LIB_DEBUG_PRINT_SAFE("Kernel : non-blocking, exiting\n"); 482 483 unlock_all( locks, count ); 484 485 LIB_DEBUG_PRINT_SAFE("Kernel : accepted %d\n", *mask.accepted); 486 return; 487 } 488 489 490 verifyf( duration < 0, "Timeout on waitfor statments not supported yet."); 491 492 LIB_DEBUG_PRINT_SAFE("Kernel : blocking waitfor\n"); 493 409 494 // Create the node specific to this wait operation 410 wait_ctx_primed( thrd, 0 ); 411 412 // Check if the entry queue 413 thread_desc * next = search_entry_queue( acceptables, acc_count, monitors, count ); 414 415 LIB_DEBUG_PRINT_SAFE("Owner(s) :"); 495 wait_ctx_primed( this_thread, 0 ); 496 497 monitor_save; 498 set_mask( monitors, count, mask ); 499 416 500 for(int i = 0; i < count; i++) { 417 LIB_DEBUG_PRINT_SAFE(" %p", monitors[i]->owner ); 418 } 419 LIB_DEBUG_PRINT_SAFE("\n"); 420 421 LIB_DEBUG_PRINT_SAFE("Passing mon to %p\n", next); 422 423 if( !next ) { 424 // Update acceptables on the current monitors 425 for(int i = 0; i < count; i++) { 426 monitors[i]->acceptables = acceptables; 427 monitors[i]->acceptable_count = acc_count; 428 } 429 } 430 else { 431 for(int i = 0; i < count; i++) { 432 set_owner( monitors[i], next ); 433 } 434 } 435 436 437 save_recursion( monitors, recursions, count ); 438 439 440 // Everything is ready to go to sleep 441 BlockInternal( locks, count, &next, next ? 1 : 0 ); 442 443 444 //WE WOKE UP 445 446 447 //We are back, restore the owners and recursions 448 lock_all( locks, count ); 449 restore_recursion( monitors, recursions, count ); 450 int acc_idx = monitors[0]->accepted_index; 451 unlock_all( locks, count ); 452 453 return acc_idx; 501 verify( monitors[i]->owner == this_thread ); 502 } 503 504 //Everything is ready to go to sleep 505 BlockInternal( locks, count ); 506 507 508 // WE WOKE UP 509 510 511 //We are back, restore the masks and recursions 512 monitor_restore; 513 514 LIB_DEBUG_PRINT_SAFE("Kernel : exiting\n"); 515 516 LIB_DEBUG_PRINT_SAFE("Kernel : accepted %d\n", *mask.accepted); 454 517 } 455 518 … … 458 521 459 522 static inline void set_owner( monitor_desc * this, thread_desc * owner ) { 523 // LIB_DEBUG_PRINT_SAFE("Kernal : Setting owner of %p to %p ( was %p)\n", this, owner, this->owner ); 524 460 525 //Pass the monitor appropriately 461 526 this->owner = owner; … … 463 528 //We are passing the monitor to someone else, which means recursion level is not 0 464 529 this->recursion = owner ? 1 : 0; 530 } 531 532 static inline void set_owner( monitor_desc ** monitors, short count, thread_desc * owner ) { 533 for( int i = 0; i < count; i++ ) { 534 set_owner( monitors[i], owner ); 535 } 536 } 537 538 static inline void set_mask( monitor_desc ** storage, short count, const __waitfor_mask_t & mask ) { 539 for(int i = 0; i < count; i++) { 540 storage[i]->mask = mask; 541 } 542 } 543 544 static inline void reset_mask( monitor_desc * this ) { 545 this->mask.accepted = NULL; 546 this->mask.clauses = NULL; 547 this->mask.size = 0; 465 548 } 466 549 … … 485 568 } 486 569 487 static inline int is_accepted( thread_desc * owner, monitor_desc * this, monitor_desc ** group, int group_cnt, void (*func)()) {488 __acceptable_t * accs = this->acceptables; // Optim489 int acc_cnt = this->acceptable_count;570 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) { 571 __acceptable_t * it = this->mask.clauses; // Optim 572 int count = this->mask.size; 490 573 491 574 // Check if there are any acceptable functions 492 if( ! accs ) return -1;575 if( !it ) return false; 493 576 494 577 // If this isn't the first monitor to test this, there is no reason to repeat the test. 495 if( this != group[0] ) return group[0]-> accepted_index;578 if( this != group[0] ) return group[0]->mask.accepted >= 0; 496 579 497 580 // For all acceptable functions check if this is the current function. 498 OUT_LOOP: 499 for( int i = 0; i < acc_cnt; i++ ) { 500 __acceptable_t * acc = &accs[i]; 501 502 // if function matches, check the monitors 503 if( acc->func == func ) { 504 505 // If the group count is different then it can't be a match 506 if( acc->count != group_cnt ) return -1; 507 508 // Check that all the monitors match 509 for( int j = 0; j < group_cnt; j++ ) { 510 // If not a match, check next function 511 if( acc->monitors[j] != group[j] ) continue OUT_LOOP; 512 } 513 514 // It's a complete match, accept the call 515 return i; 581 for( short i = 0; i < count; i++, it++ ) { 582 if( *it == group ) { 583 *this->mask.accepted = i; 584 return true; 516 585 } 517 586 } 518 587 519 588 // No function matched 520 return -1;589 return false; 521 590 } 522 591 … … 564 633 } 565 634 566 567 static inline void save_recursion ( monitor_desc ** ctx, unsigned int * /*out*/ recursions, unsigned short count ) { 635 static inline void save( monitor_desc ** ctx, short count, __attribute((unused)) spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 568 636 for( int i = 0; i < count; i++ ) { 569 637 recursions[i] = ctx[i]->recursion; 570 } 571 } 572 573 static inline void restore_recursion( monitor_desc ** ctx, unsigned int * /*in */ recursions, unsigned short count ) { 638 masks[i] = ctx[i]->mask; 639 } 640 } 641 642 static inline void restore( monitor_desc ** ctx, short count, spinlock ** locks, unsigned int * /*out*/ recursions, __waitfor_mask_t * /*out*/ masks ) { 643 lock_all( locks, count ); 574 644 for( int i = 0; i < count; i++ ) { 575 645 ctx[i]->recursion = recursions[i]; 576 } 646 ctx[i]->mask = masks[i]; 647 } 648 unlock_all( locks, count ); 577 649 } 578 650 … … 607 679 if( !this->monitors ) { 608 680 // LIB_DEBUG_PRINT_SAFE("Branding\n"); 609 assertf( thrd-> current_monitors != NULL, "No current monitor to brand condition %p", thrd->current_monitors);610 this->monitor_count = thrd-> current_monitor_count;681 assertf( thrd->monitors.list != NULL, "No current monitor to brand condition %p", thrd->monitors.list ); 682 this->monitor_count = thrd->monitors.size; 611 683 612 684 this->monitors = malloc( this->monitor_count * sizeof( *this->monitors ) ); 613 685 for( int i = 0; i < this->monitor_count; i++ ) { 614 this->monitors[i] = thrd->current_monitors[i]; 615 } 616 } 617 } 618 619 static inline unsigned short insert_unique( thread_desc ** thrds, unsigned short end, thread_desc * val ) { 620 if( !val ) return end; 621 622 for(int i = 0; i <= end; i++) { 623 if( thrds[i] == val ) return end; 624 } 625 626 thrds[end] = val; 627 return end + 1; 628 } 629 630 631 static inline bool match( __acceptable_t * acc, thread_desc * thrd ) { 632 verify( thrd ); 633 verify( acc ); 634 if( acc->func != thrd->current_monitor_func ) return false; 635 636 return true; 637 } 638 639 static inline thread_desc * search_entry_queue( __acceptable_t * acceptables, int acc_count, monitor_desc ** monitors, int count ) { 686 this->monitors[i] = thrd->monitors.list[i]; 687 } 688 } 689 } 690 691 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc ** monitors, int count ) { 640 692 641 693 __thread_queue_t * entry_queue = &monitors[0]->entry_queue; … … 644 696 for( thread_desc ** thrd_it = &entry_queue->head; 645 697 *thrd_it; 646 thrd_it = &(*thrd_it)->next )647 {698 thrd_it = &(*thrd_it)->next 699 ) { 648 700 // For each acceptable check if it matches 649 __acceptable_t * acc_end = acceptables + acc_count; 650 for( __acceptable_t * acc_it = acceptables; acc_it != acc_end; acc_it++ ) { 701 int i = 0; 702 __acceptable_t * end = mask.clauses + mask.size; 703 for( __acceptable_t * it = mask.clauses; it != end; it++, i++ ) { 651 704 // Check if we have a match 652 if( match( acc_it, *thrd_it )) {705 if( *it == (*thrd_it)->monitors ) { 653 706 654 707 // If we have a match return it 655 708 // after removeing it from the entry queue 656 return remove( entry_queue, thrd_it );709 return [remove( entry_queue, thrd_it ), i]; 657 710 } 658 711 } 659 712 } 660 713 661 return NULL; 662 } 714 return [0, -1]; 715 } 716 717 forall(dtype T | sized( T )) 718 static inline short insert_unique( T ** array, short & size, T * val ) { 719 if( !val ) return size; 720 721 for(int i = 0; i <= size; i++) { 722 if( array[i] == val ) return size; 723 } 724 725 array[size] = val; 726 size = size + 1; 727 return size; 728 } 729 730 static inline short count_max( const __waitfor_mask_t & mask ) { 731 short max = 0; 732 for( int i = 0; i < mask.size; i++ ) { 733 max += mask.clauses[i].size; 734 } 735 return max; 736 } 737 738 static inline short aggregate( monitor_desc ** storage, const __waitfor_mask_t & mask ) { 739 short size = 0; 740 for( int i = 0; i < mask.size; i++ ) { 741 for( int j = 0; j < mask.clauses[i].size; j++) { 742 insert_unique( storage, size, mask.clauses[i].list[j] ); 743 } 744 } 745 qsort( storage, size ); 746 return size; 747 } 748 663 749 void ?{}( __condition_blocked_queue_t & this ) { 664 750 this.head = NULL; -
src/libcfa/concurrency/preemption.c
r201aeb9 rd67cdb7 328 328 siginfo_t info; 329 329 int sig = sigwaitinfo( &mask, &info ); 330 331 if( sig < 0 ) { 332 //Error! 333 int err = errno; 334 switch( err ) { 335 case EAGAIN : 336 case EINTR : 337 continue; 338 case EINVAL : 339 abortf("Timeout was invalid."); 340 default: 341 abortf("Unhandled error %d", err); 342 } 343 } 330 344 331 345 // If another signal arrived something went wrong -
src/libcfa/concurrency/thread
r201aeb9 rd67cdb7 36 36 forall( dtype T | is_thread(T) ) 37 37 static inline coroutine_desc* get_coroutine(T & this) { 38 return &get_thread(this)-> cor;38 return &get_thread(this)->self_cor; 39 39 } 40 40 41 41 forall( dtype T | is_thread(T) ) 42 42 static inline monitor_desc* get_monitor(T & this) { 43 return &get_thread(this)-> mon;43 return &get_thread(this)->self_mon; 44 44 } 45 45 46 46 static inline coroutine_desc* get_coroutine(thread_desc * this) { 47 return &this-> cor;47 return &this->self_cor; 48 48 } 49 49 50 50 static inline monitor_desc* get_monitor(thread_desc * this) { 51 return &this-> mon;51 return &this->self_mon; 52 52 } 53 53 -
src/libcfa/concurrency/thread.c
r201aeb9 rd67cdb7 33 33 34 34 void ?{}(thread_desc& this) { 35 (this.cor){}; 36 this.cor.name = "Anonymous Coroutine"; 37 this.mon.owner = &this; 38 this.mon.recursion = 1; 35 (this.self_cor){}; 36 this.self_cor.name = "Anonymous Coroutine"; 37 this.self_mon.owner = &this; 38 this.self_mon.recursion = 1; 39 this.self_mon_p = &this.self_mon; 39 40 this.next = NULL; 40 41 41 this.current_monitors = &this.mon; 42 this.current_monitor_count = 1; 42 (this.monitors){ &this.self_mon_p, 1, (fptr_t)0 }; 43 43 } 44 44 45 45 void ^?{}(thread_desc& this) { 46 ^(this. cor){};46 ^(this.self_cor){}; 47 47 } 48 48 -
src/main.cc
r201aeb9 rd67cdb7 239 239 } // if 240 240 241 // OPTPRINT( "Concurrency" )242 // Concurrency::applyKeywords( translationUnit );243 244 241 // add the assignment statement after the initialization of a type parameter 245 242 OPTPRINT( "validate" ) -
src/prelude/prelude.cf
r201aeb9 rd67cdb7 42 42 _Bool ?--( _Bool & ), ?--( volatile _Bool & ); 43 43 unsigned char ?++( unsigned char & ), ?++( volatile unsigned char & ); 44 signed short ?++( signed short & ), ?++( volatile signed short & ); 45 signed short ?--( signed short & ), ?--( volatile signed short & ); 46 unsigned short ?++( unsigned short & ), ?++( volatile unsigned short & ); 47 unsigned short ?--( unsigned short & ), ?--( volatile unsigned short & ); 44 48 signed int ?++( signed int & ), ?++( volatile signed int & ); 45 49 signed int ?--( signed int & ), ?--( volatile signed int & ); … … 92 96 93 97 _Bool ++?( _Bool & ), --?( _Bool & ); 98 signed short ++?( signed short & ), --?( signed short & ); 94 99 signed int ++?( signed int & ), --?( signed int & ); 95 unsigned int ++?( unsigned int & ), --?( unsigned int & ); 100 unsigned short ++?( unsigned int & ), --?( unsigned int & ); 101 unsigned int ++?( unsigned short & ), --?( unsigned short & ); 96 102 signed long int ++?( signed long int & ), --?( signed long int & ); 97 103 unsigned long int ++?( unsigned long int & ), --?( unsigned long int & ); -
src/tests/Makefile.am
r201aeb9 rd67cdb7 22 22 concurrent = yes 23 23 quick_test += coroutine thread monitor 24 concurrent_test = coroutine thread monitor multi-monitor sched-int-b arge sched-int-block sched-int-disjoint sched-int-wait sched-ext sched-ext-multipreempt24 concurrent_test = coroutine thread monitor multi-monitor sched-int-block sched-int-disjoint sched-int-wait sched-ext-barge sched-ext-else sched-ext-parse sched-ext-statment preempt 25 25 else 26 26 concurrent=no … … 104 104 ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p -XCFA -L ${<} -o ${@} 105 105 106 sched-ext-parse : sched-ext-parse.c @CFA_BINDIR@/@CFA_NAME@ 107 ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p -XCFA -L ${<} -o ${@} 108 106 109 gmp : gmp.c @CFA_BINDIR@/@CFA_NAME@ 107 110 ${CC} ${AM_CFLAGS} ${CFLAGS} -lgmp ${<} -o ${@} -
src/tests/Makefile.in
r201aeb9 rd67cdb7 320 320 @BUILD_CONCURRENCY_TRUE@concurrent = yes 321 321 @BUILD_CONCURRENCY_FALSE@concurrent_test = 322 @BUILD_CONCURRENCY_TRUE@concurrent_test = coroutine thread monitor multi-monitor sched-int-b arge sched-int-block sched-int-disjoint sched-int-wait sched-ext sched-ext-multipreempt322 @BUILD_CONCURRENCY_TRUE@concurrent_test = coroutine thread monitor multi-monitor sched-int-block sched-int-disjoint sched-int-wait sched-ext-barge sched-ext-else sched-ext-parse sched-ext-statment preempt 323 323 324 324 # applies to both programs … … 856 856 ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p -XCFA -L ${<} -o ${@} 857 857 858 sched-ext-parse : sched-ext-parse.c @CFA_BINDIR@/@CFA_NAME@ 859 ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p -XCFA -L ${<} -o ${@} 860 858 861 gmp : gmp.c @CFA_BINDIR@/@CFA_NAME@ 859 862 ${CC} ${AM_CFLAGS} ${CFLAGS} -lgmp ${<} -o ${@} -
src/tests/sched-ext-parse.c
r201aeb9 rd67cdb7 80 80 16; 81 81 } 82 or waitfor( f 1, a, a ) {82 or waitfor( f2, a, a ) { 83 83 17; 84 84 } -
src/tests/sched-ext.c
r201aeb9 rd67cdb7 45 45 acceptable.monitors = &a; 46 46 47 __ accept_internal( 1, &acceptable );47 __waitfor_internal( 1, &acceptable ); 48 48 49 49 sout | "Accepted" | endl;
Note:
See TracChangeset
for help on using the changeset viewer.