Changes in / [f849c8e:837f999]
- Files:
-
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
Makefile.in
rf849c8e r837f999 132 132 CFA_PREFIX = @CFA_PREFIX@ 133 133 CFLAGS = @CFLAGS@ 134 CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@135 134 CPP = @CPP@ 136 135 CPPFLAGS = @CPPFLAGS@ -
config.h.in
rf849c8e r837f999 19 19 #undef CFA_PREFIX 20 20 21 /* Major.Minor */22 #undef CFA_VERSION23 24 /* Build version number. */25 #undef CFA_VERSION_BUILD26 27 /* Major.Minor.Patch.Build */28 #undef CFA_VERSION_FULL29 30 /* Major.Minor.Patch */31 #undef CFA_VERSION_LONG32 33 21 /* Major version number. */ 34 22 #undef CFA_VERSION_MAJOR … … 39 27 /* Patch version number. */ 40 28 #undef CFA_VERSION_PATCH 41 42 /* Major */43 #undef CFA_VERSION_SHORT44 29 45 30 /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP -
configure
rf849c8e r837f999 646 646 CFA_BACKEND_CC 647 647 BACKEND_CC 648 CONFIG_STATUS_DEPENDENCIES649 648 MAINT 650 649 MAINTAINER_MODE_FALSE … … 2965 2964 # may require auto* software to be installed 2966 2965 2967 ver_major=`cat version | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/\1/'` 2968 ver_minor=`cat version | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/\2/'` 2969 ver_patch=`cat version | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/\3/'` 2970 ver_build=`cat version | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/\4/'` 2971 ver_short="\"${ver_major}\"" 2972 ver__long="\"${ver_major}.${ver_minor}\"" 2973 ver__norm="\"${ver_major}.${ver_minor}.${ver_patch}\"" 2974 ver__full="\"${ver_major}.${ver_minor}.${ver_patch}.${ver_build}\"" 2975 2976 CONFIG_STATUS_DEPENDENCIES='$(top_srcdir)/version' 2977 2978 2979 cat >>confdefs.h <<_ACEOF 2980 #define CFA_VERSION_MAJOR ${ver_major} 2981 _ACEOF 2982 2983 2984 cat >>confdefs.h <<_ACEOF 2985 #define CFA_VERSION_MINOR ${ver_minor} 2986 _ACEOF 2987 2988 2989 cat >>confdefs.h <<_ACEOF 2990 #define CFA_VERSION_PATCH ${ver_patch} 2991 _ACEOF 2992 2993 2994 cat >>confdefs.h <<_ACEOF 2995 #define CFA_VERSION_BUILD ${ver_build} 2996 _ACEOF 2997 2998 2999 cat >>confdefs.h <<_ACEOF 3000 #define CFA_VERSION_SHORT ${ver_short} 3001 _ACEOF 3002 3003 3004 cat >>confdefs.h <<_ACEOF 3005 #define CFA_VERSION ${ver__long} 3006 _ACEOF 3007 3008 3009 cat >>confdefs.h <<_ACEOF 3010 #define CFA_VERSION_LONG ${ver__norm} 3011 _ACEOF 3012 3013 3014 cat >>confdefs.h <<_ACEOF 3015 #define CFA_VERSION_FULL ${ver__full} 3016 _ACEOF 2966 2967 $as_echo "#define CFA_VERSION_MAJOR \"1\"" >>confdefs.h 2968 2969 2970 $as_echo "#define CFA_VERSION_MINOR \"0\"" >>confdefs.h 2971 2972 2973 $as_echo "#define CFA_VERSION_PATCH \"0\"" >>confdefs.h 3017 2974 3018 2975 -
configure.ac
rf849c8e r837f999 18 18 AM_MAINTAINER_MODE(enable) # may require auto* software to be installed 19 19 20 ver_major=`cat version | sed -r 's/([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)/\1/'` 21 ver_minor=`cat version | sed -r 's/([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)/\2/'` 22 ver_patch=`cat version | sed -r 's/([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)/\3/'` 23 ver_build=`cat version | sed -r 's/([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)\.([[0-9]]+)/\4/'` 24 ver_short="\"${ver_major}\"" 25 ver__long="\"${ver_major}.${ver_minor}\"" 26 ver__norm="\"${ver_major}.${ver_minor}.${ver_patch}\"" 27 ver__full="\"${ver_major}.${ver_minor}.${ver_patch}.${ver_build}\"" 28 29 AC_SUBST([CONFIG_STATUS_DEPENDENCIES], ['$(top_srcdir)/version']) 30 AC_DEFINE_UNQUOTED(CFA_VERSION_MAJOR, ${ver_major}, [Major version number.]) 31 AC_DEFINE_UNQUOTED(CFA_VERSION_MINOR, ${ver_minor}, [Minor version number.]) 32 AC_DEFINE_UNQUOTED(CFA_VERSION_PATCH, ${ver_patch}, [Patch version number.]) 33 AC_DEFINE_UNQUOTED(CFA_VERSION_BUILD, ${ver_build}, [Build version number.]) 34 AC_DEFINE_UNQUOTED(CFA_VERSION_SHORT, ${ver_short}, [Major]) 35 AC_DEFINE_UNQUOTED(CFA_VERSION, ${ver__long}, [Major.Minor]) 36 AC_DEFINE_UNQUOTED(CFA_VERSION_LONG, ${ver__norm}, [Major.Minor.Patch]) 37 AC_DEFINE_UNQUOTED(CFA_VERSION_FULL, ${ver__full}, [Major.Minor.Patch.Build]) 20 AC_DEFINE(CFA_VERSION_MAJOR, "1", [Major version number.]) 21 AC_DEFINE(CFA_VERSION_MINOR, "0", [Minor version number.]) 22 AC_DEFINE(CFA_VERSION_PATCH, "0", [Patch version number.]) 38 23 39 24 # Installation paths -
doc/proposals/concurrency/concurrency.tex
rf849c8e r837f999 90 90 91 91 \maketitle 92 93 % ### # # ####### ###### #######94 % # ## # # # # # #95 % # # # # # # # # #96 % # # # # # ###### # #97 % # # # # # # # # #98 % # # ## # # # # #99 % ### # # # # # #######100 101 92 \section{Introduction} 102 93 This proposal provides a minimal core concurrency API that is both simple, efficient and can be reused to build higher-level features. The simplest possible core 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 construct as the basis of the concurrency in \CFA. … … 105 96 There are actually two problems that need to be solved in the design of the concurrency for a language. Which concurrency tools are available to the users and which parallelism tools are available. While these two concepts are often seen together, they are in fact distinct concepts that require different sorts of tools\cite{Buhr05a}. Concurrency tools need to handle mutual exclusion and synchronization while parallelism tools are more about performance, cost and resource utilization. 106 97 107 % ##### ####### # # ##### # # ###### ###### ####### # # ##### # #108 % # # # # ## # # # # # # # # # # ## # # # # #109 % # # # # # # # # # # # # # # # # # # # #110 % # # # # # # # # # ###### ###### ##### # # # # #111 % # # # # # # # # # # # # # # # # # # #112 % # # # # # ## # # # # # # # # # # ## # # #113 % ##### ####### # # ##### ##### # # # # ####### # # ##### #114 115 98 \section{Concurrency} 116 % Several tool can be used to solve concurrency challenges. Since these challenges always appear with the use of mutable shared state, some languages and libraries simply disallow mutable shared-state (Erlang\cite{Erlang}, Haskell\cite{Haskell}, Akka (Scala)\cite{Akka}). In these paradigms, interaction among concurrent objects rely on message passing or other paradigms that often closely relate to networking concepts. However, in imperative or OO languages, these approaches entail a clear distinction between concurrent and non-concurrent paradigms (i.e. message passing versus routine call). Which in turns mean that programmers need to learn two sets of designs patterns in order to be effective. Approaches based on shared memory are more closely related to non-concurrent paradigms since they often rely on non-concurrent constructs like routine calls and objects. At a lower level these can be implemented as locks and atomic operations. However, for productivity reasons it is desireable to have a higher-level construct to be the core concurrency paradigm\cite{HPP:Study}. This project proposes Monitors\cite{Hoare74} as the core concurrency construct. 117 % \\ 118 119 Several tool can be used to solve concurrency challenges. Since these challenges always appear with the use of mutable shared state, some languages and libraries simply disallow mutable shared-state (Erlang\cite{Erlang}, Haskell\cite{Haskell}, Akka (Scala)\cite{Akka}). In these paradigms, interaction among concurrent objects rely on message passing\cite{Thoth,Harmony,V-Kernel} or other paradigms that often closely relate to networking concepts. However, in imperative or OO languages, these approaches entail a clear distinction between concurrent and non-concurrent paradigms (i.e. message passing versus routine call). Which in turns mean that programmers need to learn two sets of designs patterns in order to be effective. Approaches based on shared memory are more closely related to non-concurrent paradigms since they often rely on non-concurrent constructs like routine calls and objects. At a lower level these can be implemented as locks and atomic operations. Many such mechanisms have been proposed, including semaphores~\cite{Dijkstra68b} and path expressions~\cite{Campbell74}. However, for productivity reasons it is desireable to have a higher-level construct to be the core concurrency paradigm\cite{HPP:Study}. One of the most natural, elegant, and efficient mechanisms for synchronization and communication, especially for shared memory systems, is the \emph{monitor}. 120 121 Monitors were first proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}. 122 Many programming languages---e.g., Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Modula~\cite{Modula-2}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, NeWS~\cite{NeWS}, Emerald~\cite{Emerald}, \uC~\cite{Buhr92a} and Java~\cite{Java}---provide monitors as explicit language constructs. In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as semaphores or locks to simulate monitors. For these reasons, this project proposes Monitors as the core concurrency construct. 99 Several tool can be used to solve concurrency challenges. Since these challenges always appear with the use of mutable shared state, some languages and libraries simply disallow mutable shared-state (Erlang\cite{Erlang}, Haskell\cite{Haskell}, Akka (Scala)\cite{Akka}). In these paradigms, interaction among concurrent objects rely on message passing or other paradigms that often closely relate to networking concepts. However, in imperative or OO languages, these approaches entail a clear distinction between concurrent and non-concurrent paradigms (i.e. message passing versus routine call). Which in turns mean that programmers need to learn two sets of designs patterns in order to be effective. Approaches based on shared memory are more closely related to non-concurrent paradigms since they often rely on non-concurrent constructs like routine calls and objects. At a lower level these can be implemented as locks and atomic operations. However, for productivity reasons it is desireable to have a higher-level construct to be the core concurrency paradigm\cite{HPP:Study}. This project proposes Monitors\cite{Hoare74} as the core concurrency construct. 123 100 \\ 124 101 125 102 Finally, an approach that is worth mentionning because it is gaining in popularity is transactionnal memory\cite{Dice10}. However, the performance and feature set is currently too restrictive to be possible to add such a paradigm to a language like C or \CC\cit, which is why it was rejected as the core paradigm for concurrency in \CFA. 126 127 % # # ####### # # ### ####### ####### ###### #####128 % ## ## # # ## # # # # # # # # #129 % # # # # # # # # # # # # # # # #130 % # # # # # # # # # # # # ###### #####131 % # # # # # # # # # # # # # #132 % # # # # # ## # # # # # # # #133 % # # ####### # # ### # ####### # # #####134 103 135 104 \subsection{Monitors} … … 144 113 } 145 114 \end{lstlisting} 146 147 % ##### # # #148 % # # # # # #149 % # # # # #150 % # # # # #151 % # ####### # #152 % # # # # # #153 % ##### # # ####### #######154 115 155 116 \subsubsection{Call semantics} \label{call} … … 187 148 The problem is to indentify which object(s) should be acquired. Furthermore we also need to acquire each objects only once. In case of simple routines like \code{f1} and \code{f2} it is easy to identify an exhaustive list of objects to acquire on entering. Adding indirections (\code{f3}) still allows the compiler and programmer to indentify which object will be acquired. However, adding in arrays (\code{f4}) makes it much harder. Array lengths aren't necessarily known in C and even then making sure we only acquire objects once becomes also none trivial. This can be extended to absurd limits like \code{f5} which uses a custom 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 (ignoring potential qualifiers and indirections). 188 149 189 % ###### # ####### #190 % # # # # # # #191 % # # # # # # #192 % # # # # # # #193 % # # ####### # #######194 % # # # # # # #195 % ###### # # # # #196 197 150 \subsubsection{Data semantics} \label{data} 198 151 Once the call semantics are established, the next step is to establish data semantics. Indeed, until now a monitor is used simply as a generic handle but in most cases monitors contian shared data. This data should be intrinsic to the monitor declaration to prevent any accidental use of data without its appripriate protection. For example here is a more fleshed-out version of the counter showed in \ref{call}: … … 266 219 Recursive mutex routine calls are allowed in \CFA but if not done carefully it can lead to nested monitor call problems\cite{Lister77}. These problems which are a specific implementation of the lock acquiring order problem. In the example above, the user uses implicit ordering in the case of function \code{bar} but explicit ordering in the case of \code{baz}. This subtle mistake can mean that calling these two functions concurrently will lead to deadlocks, depending on the implicit ordering matching the explicit ordering. As shown on several occasion\cit, there isn't really any solutions to this problem, users simply need to be carefull when acquiring multiple monitors at the same time. 267 220 268 % ###### ####### ####### # ### # #####269 % # # # # # # # # # #270 % # # # # # # # # #271 % # # ##### # # # # # #####272 % # # # # ####### # # #273 % # # # # # # # # # #274 % ###### ####### # # # ### ####### #####275 %276 % ###### ####### # # # # # ####### ###### # #277 % # # # # # # # ## ## # # # # # #278 % # # # # # # # # # # # # # # # # #279 % ##### ###### # # # # # # # # # ###### #######280 % # # # # # # # # # # # # #281 % # # # # # # # # # # # # #282 % # ####### ####### # # # ####### # # # #283 284 221 \subsubsection{Implementation Details: Interaction with polymorphism} 285 222 At first glance, interaction between monitors and \CFA's concept of polymorphism seem complexe to support. However, it can be reasoned that entry-point locking can solve most of the issues that could be present with polymorphism. 286 223 287 224 First of all, interaction between \code{otype} polymorphism and monitors is impossible since monitors do not support copying. Therefore the main question is how to support \code{dtype} polymorphism. We must remember that monitors' main purpose is to ensure mutual exclusion when accessing shared data. This implies that mutual exclusion is only required for routines that do in fact access shared data. However, since \code{dtype} polymorphism always handle incomplete types (by definition) no \code{dtype} polymorphic routine can access shared data since the data would require knowledge about the type. Therefore the only concern when combining \code{dtype} polymorphism and monitors is to protect access to routines. With callsite-locking, this would require significant amount of work since any \code{dtype} routine could have to obtain some lock before calling a routine. However, with entry-point-locking calling a monitor routine becomes exactly the same as calling it from anywhere else. 288 289 % ### # # ####### ##### ##### # # ####### ######290 % # ## # # # # # # # # # # #291 % # # # # # # # # # # # #292 % # # # # # ##### # ####### ##### # #293 % # # # # # ### # # # # # # #294 % # # ## # ### # # # # # # # # #295 % ### # # # ### ##### ##### # # ####### ######296 225 297 226 \subsection{Internal scheduling} \label{insched} … … 538 467 \\ 539 468 540 % ####### # # ####### ##### ##### # # ####### ######541 % # # # # # # # # # # # # #542 % # # # # # # # # # # #543 % ##### # # ##### # ####### ##### # #544 % # # # # ### # # # # # # #545 % # # # # ### # # # # # # # # #546 % ####### # # # ### ##### ##### # # ####### ######547 548 469 \subsection{External scheduling} \label{extsched} 549 470 As one might expect, the alternative to Internal scheduling is to use External scheduling instead. This method is somewhat more robust to deadlocks since one of the threads keeps a relatively tight control on scheduling. Indeed, as the following examples will demonstrate, external scheduling allows users to wait for events from other threads without the concern of unrelated events occuring. External scheduling can generally be done either in terms of control flow (ex: \uC) or in terms of data (ex: Go). Of course, both of these paradigms have their own strenghts and weaknesses but for this project control flow semantics where chosen to stay consistent with the rest of the languages semantics. Two challenges specific to \CFA arise when trying to add external scheduling with loose object definitions and multi-monitor routines. The following example shows what a simple use \code{accept} versus \code{wait}/\code{signal} and its advantages. … … 575 496 In the case of internal scheduling, the call to \code{wait} only guarantees that \code{g} was the last routine to access the monitor. This intails that the routine \code{f} may have acquired mutual exclusion several times while routine \code{h} was waiting. On the other hand, external scheduling guarantees that while routine \code{h} was waiting, no routine other than \code{g} could acquire the monitor. 576 497 \\ 577 578 % # ####### ####### ##### ####### ####### ###### # #####579 % # # # # # # # # # # # # # # #580 % # # # # # # # # # # # # #581 % # # # # # ##### ##### # # ###### # #####582 % # # # # # # # # # # # # # #583 % # # # # # # # # # # # # # # # #584 % ####### ####### ####### ##### ####### ####### ###### ##### #####585 498 586 499 \subsubsection{Loose object definitions} … … 674 587 An other aspect to consider is what happens if multiple overloads of the same routine are used. For the time being it is assumed that multiple overloads of the same routine should be scheduled regardless of the overload used. However, this could easily be extended in the future. 675 588 676 % # # # # # ####### ### # # ####### # #677 % ## ## # # # # # ## ## # # ## #678 % # # # # # # # # # # # # # # # # # #679 % # # # # # # # # # # # # # # # #680 % # # # # # # # # # # # # # #681 % # # # # # # # # # # # # ##682 % # # ##### ####### # ### # # ####### # #683 684 589 \subsubsection{Multi-monitor scheduling} 685 590 … … 724 629 Note that the set of monitors passed to the \code{accept} statement must be entirely contained in the set of monitor already acquired in the routine. \code{accept} used in any other context is Undefined Behaviour. 725 630 726 % ###### ####### ####### # ### # #####727 % # # # # # # # # # #728 % # # # # # # # # #729 % # # ##### # # # # # #####730 % # # # # ####### # # #731 % # # # # # # # # # #732 % ###### ####### # # # ### ####### #####733 %734 % ##### # # ####### # # ####### #####735 % # # # # # # # # # #736 % # # # # # # # # #737 % ##### # # # # ##### # # ##### #####738 % # # # # # # # # # #739 % # # # # # # # # # #740 % #### # ##### ####### ##### ####### #####741 742 743 631 \subsubsection{Implementation Details: External scheduling queues} 744 632 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 reasonnable 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. … … 748 636 749 637 \newpage 750 % ###### # ###### # # # ####### # ### ##### # #751 % # # # # # # # # # # # # # # # ## ##752 % # # # # # # # # # # # # # # # # # #753 % ###### # # ###### # # # # ##### # # ##### # # #754 % # ####### # # ####### # # # # # # # #755 % # # # # # # # # # # # # # # # #756 % # # # # # # # ####### ####### ####### ####### ### ##### # #757 638 \section{Parallelism} 758 639 Historically, computer performance was about processor speeds and instructions count. However, with heat dissipation being an ever growing challenge, parallelism has become the new source of greatest performance \cite{Sutter05, Sutter05b}. In this decade, it is not longer reasonnable to create high-performance application without caring about parallelism. Indeed, parallelism is an important aspect of performance and more specifically throughput and hardware utilization. The lowest level approach of parallelism is to use \glspl{kthread}. However since these have significant costs and limitations \glspl{kthread} are now mostly used as an implementation tool rather than a user oriented one. There are several alternatives to solve these issues which all have strengths and weaknesses. … … 774 655 While the choice between the three paradigms listed above may have significant performance implication, it is difficult to pin the performance implications of chosing a model at the language level. Indeed, in many situations one of these paradigms will show better performance but it all strongly depends on the usage. Having mostly indepent units of work to execute almost guarantess that the \gls{job} based system will have the best performance. However, add interactions between jobs and the processor utilisation might suffer. User-level threads may allow maximum ressource utilisation but context switches will be more expansive and it is also harder for users to get perfect tunning. As with every example, fibers sit somewhat in the middle of the spectrum. Furthermore, if the units of uninterrupted work are large enough the paradigm choice will be largely amorticised by the actual work done. 775 656 776 % ##### ####### # ####### ###### ######777 % # # # # # # # # # #778 % # # # # # # # # #779 % # ##### # # ##### # ###### ######780 % # # ####### # # # # #781 % # # # # # # # # # #782 % ##### # # # # ###### ######783 784 657 \section{\CFA 's Thread Building Blocks} 785 658 As a system level language, \CFA should offer both performance and flexibilty as its primary goals, simplicity and user-friendliness being a secondary concern. Therefore, the core of parallelism in \CFA should prioritize power and efficiency. With this said, it is possible to deconstruct the three paradigms details aboved in order to get simple building blocks. Here is a table showing the core caracteristics of the mentionned paradigms : … … 799 672 800 673 As shown in section \ref{cfaparadigms} these different blocks being available in \CFA it is trivial to reproduce any of these paradigm. 801 802 % ####### # # ###### ####### # ###### #####803 % # # # # # # # # # # # #804 % # # # # # # # # # # #805 % # ####### ###### ##### # # # # #####806 % # # # # # # ####### # # #807 % # # # # # # # # # # # #808 % # # # # # ####### # # ###### #####809 674 810 675 \subsection{Thread Interface} … … 978 843 % \textbf{\large{Work in progress...}} Do wee need something beyond specifying the number of kernel threads? 979 844 980 % # # #981 % # # # #982 % # # # #983 % # # # #984 % ####### # #985 % # # # #986 % # # ####### #######987 845 \section{Putting it all together} 988 846 989 990 991 992 993 994 995 996 997 998 % ####### # # ####### # # ###### #######999 % # # # # # # # # #1000 % # # # # # # # # #1001 % ##### # # # # # ###### #####1002 % # # # # # # # # #1003 % # # # # # # # # #1004 % # ##### # ##### # # ######1005 847 \section{Future work} 1006 848 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. 1007 849 \subsection{Transactions} 1008 850 1009 % ####### # # ######1010 % # ## # # #1011 % # # # # # #1012 % ##### # # # # #1013 % # # # # # #1014 % # # ## # #1015 % ####### # # ######1016 851 \section*{Acknowledgements} 1017 852 … … 1022 857 \clearpage 1023 858 \bibliographystyle{plain} 1024 \bibliography{ cw92,distSharedMem,lfp92,mlw92,parallel,parallelIO,partheory,pl,pldi92,ps,realtime,techreportsPAB,visual,local}859 \bibliography{pl,local} 1025 860 1026 861 -
doc/proposals/concurrency/version
rf849c8e r837f999 1 0.4.9 91 0.4.95 -
src/ControlStruct/LabelFixer.h
rf849c8e r837f999 26 26 namespace ControlStruct { 27 27 /// normalizes label definitions and generates multi-level exit labels 28 class LabelFixer final: public Visitor {28 class LabelFixer : public Visitor { 29 29 typedef Visitor Parent; 30 30 public: … … 33 33 std::map < Label, Statement * > *resolveJumps() throw ( SemanticError ); 34 34 35 using Visitor::visit;36 37 35 // Declarations 38 virtual void visit( FunctionDecl *functionDecl ) override;36 virtual void visit( FunctionDecl *functionDecl ); 39 37 40 38 // Statements 41 39 void visit( Statement *stmt ); 42 40 43 virtual void visit( CompoundStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }44 virtual void visit( NullStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }45 virtual void visit( ExprStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }46 virtual void visit( IfStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }47 virtual void visit( WhileStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }48 virtual void visit( ForStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }49 virtual void visit( SwitchStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }50 virtual void visit( CaseStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }51 virtual void visit( ReturnStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }52 virtual void visit( TryStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }53 virtual void visit( CatchStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }54 virtual void visit( DeclStmt *stmt ) override{ visit( (Statement *)stmt ); return Parent::visit( stmt ); }55 virtual void visit( BranchStmt *branchStmt ) override;56 virtual void visit( UntypedExpr *untyped ) override;41 virtual void visit( CompoundStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 42 virtual void visit( NullStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 43 virtual void visit( ExprStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 44 virtual void visit( IfStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 45 virtual void visit( WhileStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 46 virtual void visit( ForStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 47 virtual void visit( SwitchStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 48 virtual void visit( CaseStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 49 virtual void visit( ReturnStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 50 virtual void visit( TryStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 51 virtual void visit( CatchStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 52 virtual void visit( DeclStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); } 53 virtual void visit( BranchStmt *branchStmt ); 54 virtual void visit( UntypedExpr *untyped ); 57 55 58 56 Label setLabelsDef( std::list< Label > &, Statement *definition ); -
src/ControlStruct/LabelTypeChecker.cc
rf849c8e r837f999 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // LabelTypeChecker.cc -- 7 // LabelTypeChecker.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 28 28 assert( untypedExpr != 0 ); 29 29 NameExpr *fname; 30 if ( ((fname = dynamic_cast<NameExpr *>(untypedExpr->get_function())) != 0) 30 if ( ((fname = dynamic_cast<NameExpr *>(untypedExpr->get_function())) != 0) 31 31 && fname->get_name() == std::string("&&") ) 32 32 std::cerr << "Taking the label of an address." << std::endl; … … 58 58 59 59 NameExpr *name; 60 if ( ( name = dynamic_cast<NameExpr *>(target)) == 0)60 if ( ((name = dynamic_cast<NameExpr *>(target)) == 0) ) 61 61 return; // Not a name expression 62 62 63 63 std::list< DeclarationWithType * > interps; 64 64 index.lookupId(name->get_name(), interps); -
src/GenPoly/Box.cc
rf849c8e r837f999 64 64 65 65 /// Adds layout-generation functions to polymorphic types 66 class LayoutFunctionBuilder final: public DeclMutator {66 class LayoutFunctionBuilder : public DeclMutator { 67 67 unsigned int functionNesting; // current level of nested functions 68 68 public: 69 69 LayoutFunctionBuilder() : functionNesting( 0 ) {} 70 70 71 using DeclMutator::mutate; 72 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override; 73 virtual Declaration *mutate( StructDecl *structDecl ) override; 74 virtual Declaration *mutate( UnionDecl *unionDecl ) override; 71 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ); 72 virtual Declaration *mutate( StructDecl *structDecl ); 73 virtual Declaration *mutate( UnionDecl *unionDecl ); 75 74 }; 76 75 77 76 /// 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 78 class Pass1 final: public PolyMutator {77 class Pass1 : public PolyMutator { 79 78 public: 80 79 Pass1(); 81 82 using PolyMutator::mutate; 83 virtual Expression *mutate( ApplicationExpr *appExpr ) override; 84 virtual Expression *mutate( AddressExpr *addrExpr ) override; 85 virtual Expression *mutate( UntypedExpr *expr ) override; 86 virtual DeclarationWithType* mutate( FunctionDecl *functionDecl ) override; 87 virtual TypeDecl *mutate( TypeDecl *typeDecl ) override; 88 virtual Expression *mutate( CommaExpr *commaExpr ) override; 89 virtual Expression *mutate( ConditionalExpr *condExpr ) override; 90 virtual Statement * mutate( ReturnStmt *returnStmt ) override; 91 virtual Type *mutate( PointerType *pointerType ) override; 92 virtual Type * mutate( FunctionType *functionType ) override; 93 94 virtual void doBeginScope() override; 95 virtual void doEndScope() override; 80 virtual Expression *mutate( ApplicationExpr *appExpr ); 81 virtual Expression *mutate( AddressExpr *addrExpr ); 82 virtual Expression *mutate( UntypedExpr *expr ); 83 virtual DeclarationWithType* mutate( FunctionDecl *functionDecl ); 84 virtual TypeDecl *mutate( TypeDecl *typeDecl ); 85 virtual Expression *mutate( CommaExpr *commaExpr ); 86 virtual Expression *mutate( ConditionalExpr *condExpr ); 87 virtual Statement * mutate( ReturnStmt *returnStmt ); 88 virtual Type *mutate( PointerType *pointerType ); 89 virtual Type * mutate( FunctionType *functionType ); 90 91 virtual void doBeginScope(); 92 virtual void doEndScope(); 96 93 private: 97 94 /// Pass the extra type parameters from polymorphic generic arguments or return types into a function application … … 138 135 /// * Moves polymorphic returns in function types to pointer-type parameters 139 136 /// * adds type size and assertion parameters to parameter lists 140 class Pass2 final: public PolyMutator {137 class Pass2 : public PolyMutator { 141 138 public: 142 139 template< typename DeclClass > 143 140 DeclClass *handleDecl( DeclClass *decl, Type *type ); 144 145 using PolyMutator::mutate; 146 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override; 147 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override; 148 virtual TypeDecl *mutate( TypeDecl *typeDecl ) override; 149 virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ) override; 150 virtual Type *mutate( PointerType *pointerType ) override; 151 virtual Type *mutate( FunctionType *funcType ) override; 141 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ); 142 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ); 143 virtual TypeDecl *mutate( TypeDecl *typeDecl ); 144 virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ); 145 virtual Type *mutate( PointerType *pointerType ); 146 virtual Type *mutate( FunctionType *funcType ); 152 147 153 148 private: … … 161 156 /// * Calculates polymorphic offsetof expressions from offset array 162 157 /// * Inserts dynamic calculation of polymorphic type layouts where needed 163 class PolyGenericCalculator final: public PolyMutator {158 class PolyGenericCalculator : public PolyMutator { 164 159 public: 165 160 typedef PolyMutator Parent; … … 168 163 template< typename DeclClass > 169 164 DeclClass *handleDecl( DeclClass *decl, Type *type ); 170 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;171 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;172 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ) override;173 virtual TypeDecl *mutate( TypeDecl *objectDecl ) override;174 virtual Statement *mutate( DeclStmt *declStmt ) override;175 virtual Type *mutate( PointerType *pointerType ) override;176 virtual Type *mutate( FunctionType *funcType ) override;177 virtual Expression *mutate( MemberExpr *memberExpr ) override;178 virtual Expression *mutate( SizeofExpr *sizeofExpr ) override;179 virtual Expression *mutate( AlignofExpr *alignofExpr ) override;180 virtual Expression *mutate( OffsetofExpr *offsetofExpr ) override;181 virtual Expression *mutate( OffsetPackExpr *offsetPackExpr ) override;182 183 virtual void doBeginScope() override;184 virtual void doEndScope() override;165 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ); 166 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ); 167 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ); 168 virtual TypeDecl *mutate( TypeDecl *objectDecl ); 169 virtual Statement *mutate( DeclStmt *declStmt ); 170 virtual Type *mutate( PointerType *pointerType ); 171 virtual Type *mutate( FunctionType *funcType ); 172 virtual Expression *mutate( MemberExpr *memberExpr ); 173 virtual Expression *mutate( SizeofExpr *sizeofExpr ); 174 virtual Expression *mutate( AlignofExpr *alignofExpr ); 175 virtual Expression *mutate( OffsetofExpr *offsetofExpr ); 176 virtual Expression *mutate( OffsetPackExpr *offsetPackExpr ); 177 178 virtual void doBeginScope(); 179 virtual void doEndScope(); 185 180 186 181 private: … … 202 197 203 198 /// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable 204 class Pass3 final: public PolyMutator {199 class Pass3 : public PolyMutator { 205 200 public: 206 201 template< typename DeclClass > 207 202 DeclClass *handleDecl( DeclClass *decl, Type *type ); 208 209 using PolyMutator::mutate; 210 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override; 211 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override; 212 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ) override; 213 virtual TypeDecl *mutate( TypeDecl *objectDecl ) override; 214 virtual Type *mutate( PointerType *pointerType ) override; 215 virtual Type *mutate( FunctionType *funcType ) override; 203 virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ); 204 virtual ObjectDecl *mutate( ObjectDecl *objectDecl ); 205 virtual TypedefDecl *mutate( TypedefDecl *objectDecl ); 206 virtual TypeDecl *mutate( TypeDecl *objectDecl ); 207 virtual Type *mutate( PointerType *pointerType ); 208 virtual Type *mutate( FunctionType *funcType ); 216 209 private: 217 210 }; -
src/GenPoly/InstantiateGeneric.cc
rf849c8e r837f999 147 147 148 148 /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately 149 class GenericInstantiator final: public DeclMutator {149 class GenericInstantiator : public DeclMutator { 150 150 /// Map of (generic type, parameter list) pairs to concrete type instantiations 151 151 InstantiationMap< AggregateDecl, AggregateDecl > instantiations; … … 158 158 GenericInstantiator() : DeclMutator(), instantiations(), dtypeStatics(), typeNamer("_conc_") {} 159 159 160 using DeclMutator::mutate; 161 virtual Type* mutate( StructInstType *inst ) override; 162 virtual Type* mutate( UnionInstType *inst ) override; 163 164 virtual void doBeginScope() override; 165 virtual void doEndScope() override; 160 virtual Type* mutate( StructInstType *inst ); 161 virtual Type* mutate( UnionInstType *inst ); 162 163 virtual void doBeginScope(); 164 virtual void doEndScope(); 166 165 private: 167 166 /// Wrap instantiation lookup for structs -
src/GenPoly/Specialize.cc
rf849c8e r837f999 36 36 const std::list<Label> noLabels; 37 37 38 class Specialize final: public PolyMutator {38 class Specialize : public PolyMutator { 39 39 public: 40 40 Specialize( std::string paramPrefix = "_p" ); 41 41 42 using PolyMutator::mutate; 43 virtual Expression * mutate( ApplicationExpr *applicationExpr ) override; 44 virtual Expression * mutate( AddressExpr *castExpr ) override; 45 virtual Expression * mutate( CastExpr *castExpr ) override; 42 virtual Expression * mutate( ApplicationExpr *applicationExpr ); 43 virtual Expression * mutate( AddressExpr *castExpr ); 44 virtual Expression * mutate( CastExpr *castExpr ); 46 45 // virtual Expression * mutate( LogicalExpr *logicalExpr ); 47 46 // virtual Expression * mutate( ConditionalExpr *conditionalExpr ); -
src/InitTweak/FixInit.cc
rf849c8e r837f999 50 50 const std::list<Expression*> noDesignators; 51 51 52 class InsertImplicitCalls final: public GenPoly::PolyMutator {52 class InsertImplicitCalls : public GenPoly::PolyMutator { 53 53 public: 54 54 /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which … … 56 56 static void insert( std::list< Declaration * > & translationUnit ); 57 57 58 using GenPoly::PolyMutator::mutate; 59 virtual Expression * mutate( ApplicationExpr * appExpr ) override; 60 }; 61 62 class ResolveCopyCtors final : public SymTab::Indexer { 58 virtual Expression * mutate( ApplicationExpr * appExpr ); 59 }; 60 61 class ResolveCopyCtors : public SymTab::Indexer { 63 62 public: 64 63 /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr, … … 67 66 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 68 67 69 using SymTab::Indexer::visit; 70 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 68 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 71 69 72 70 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) … … 84 82 using Parent::visit; 85 83 typedef std::set< ObjectDecl * > ObjectSet; 86 virtual void visit( CompoundStmt *compoundStmt ) override;87 virtual void visit( DeclStmt *stmt ) override;84 virtual void visit( CompoundStmt *compoundStmt ); 85 virtual void visit( DeclStmt *stmt ); 88 86 protected: 89 87 ObjectSet curVars; … … 105 103 } 106 104 107 class LabelFinder final: public ObjDeclCollector {105 class LabelFinder : public ObjDeclCollector { 108 106 public: 109 107 typedef ObjDeclCollector Parent; … … 119 117 // subclasses are added, there is only one place that the code has to be updated, rather than ensure that 120 118 // every specialized class knows about every new kind of statement that might be added. 121 using Parent::visit; 122 virtual void visit( CompoundStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 123 virtual void visit( ExprStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 124 virtual void visit( AsmStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 125 virtual void visit( IfStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 126 virtual void visit( WhileStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 127 virtual void visit( ForStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 128 virtual void visit( SwitchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 129 virtual void visit( CaseStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 130 virtual void visit( BranchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 131 virtual void visit( ReturnStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 132 virtual void visit( TryStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 133 virtual void visit( CatchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 134 virtual void visit( FinallyStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 135 virtual void visit( NullStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 136 virtual void visit( DeclStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 137 virtual void visit( ImplicitCtorDtorStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); } 138 }; 139 140 class InsertDtors final : public ObjDeclCollector { 119 virtual void visit( CompoundStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 120 virtual void visit( ExprStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 121 virtual void visit( AsmStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 122 virtual void visit( IfStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 123 virtual void visit( WhileStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 124 virtual void visit( ForStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 125 virtual void visit( SwitchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 126 virtual void visit( CaseStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 127 virtual void visit( BranchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 128 virtual void visit( ReturnStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 129 virtual void visit( TryStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 130 virtual void visit( CatchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 131 virtual void visit( FinallyStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 132 virtual void visit( NullStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 133 virtual void visit( DeclStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 134 virtual void visit( ImplicitCtorDtorStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 135 }; 136 137 class InsertDtors : public ObjDeclCollector { 141 138 public: 142 139 /// insert destructor calls at the appropriate places. must happen before CtorInit nodes are removed … … 150 147 InsertDtors( LabelFinder & finder ) : labelVars( finder.vars ) {} 151 148 152 using Parent::visit; 153 154 virtual void visit( ObjectDecl * objDecl ) override; 155 156 virtual void visit( CompoundStmt * compoundStmt ) override; 157 virtual void visit( ReturnStmt * returnStmt ) override; 158 virtual void visit( BranchStmt * stmt ) override; 149 virtual void visit( ObjectDecl * objDecl ); 150 151 virtual void visit( CompoundStmt * compoundStmt ); 152 virtual void visit( ReturnStmt * returnStmt ); 153 virtual void visit( BranchStmt * stmt ); 159 154 private: 160 155 void handleGoto( BranchStmt * stmt ); … … 164 159 }; 165 160 166 class FixInit final: public GenPoly::PolyMutator {161 class FixInit : public GenPoly::PolyMutator { 167 162 public: 168 163 /// expand each object declaration to use its constructor after it is declared. 169 164 static void fixInitializers( std::list< Declaration * > &translationUnit ); 170 165 171 using GenPoly::PolyMutator::mutate; 172 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ) override; 166 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 173 167 174 168 std::list< Declaration * > staticDtorDecls; 175 169 }; 176 170 177 class FixCopyCtors final: public GenPoly::PolyMutator {171 class FixCopyCtors : public GenPoly::PolyMutator { 178 172 public: 179 173 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression, … … 181 175 static void fixCopyCtors( std::list< Declaration * > &translationUnit ); 182 176 183 using GenPoly::PolyMutator::mutate; 184 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 185 }; 186 187 class GenStructMemberCalls final : public SymTab::Indexer { 177 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 178 }; 179 180 class GenStructMemberCalls : public SymTab::Indexer { 188 181 public: 189 182 typedef Indexer Parent; … … 193 186 static void generate( std::list< Declaration * > & translationUnit ); 194 187 195 using Parent::visit; 196 197 virtual void visit( FunctionDecl * funcDecl ) override; 198 199 virtual void visit( MemberExpr * memberExpr ) override; 200 virtual void visit( ApplicationExpr * appExpr ) override; 188 virtual void visit( FunctionDecl * funcDecl ); 189 190 virtual void visit( MemberExpr * memberExpr ); 191 virtual void visit( ApplicationExpr * appExpr ); 201 192 202 193 SemanticError errors; … … 216 207 // resolve UntypedExprs that are found within newly 217 208 // generated constructor/destructor calls 218 class MutatingResolver final: public Mutator {209 class MutatingResolver : public Mutator { 219 210 public: 220 211 MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {} 221 212 222 using Mutator::mutate; 223 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override; 224 virtual Expression* mutate( UntypedExpr *untypedExpr ) override; 225 226 private: 213 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ); 214 215 virtual Expression* mutate( UntypedExpr *untypedExpr ); 216 private: 227 217 SymTab::Indexer & indexer; 228 218 }; 229 219 230 class FixCtorExprs final: public GenPoly::DeclMutator {220 class FixCtorExprs : public GenPoly::DeclMutator { 231 221 public: 232 222 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 233 223 static void fix( std::list< Declaration * > & translationUnit ); 234 224 235 using GenPoly::DeclMutator::mutate; 236 virtual Expression * mutate( ConstructorExpr * ctorExpr ) override; 225 virtual Expression * mutate( ConstructorExpr * ctorExpr ); 237 226 }; 238 227 } // namespace -
src/InitTweak/GenInit.cc
rf849c8e r837f999 36 36 } 37 37 38 class ReturnFixer final: public GenPoly::PolyMutator {38 class ReturnFixer : public GenPoly::PolyMutator { 39 39 public: 40 40 /// consistently allocates a temporary variable for the return value … … 45 45 ReturnFixer(); 46 46 47 using GenPoly::PolyMutator::mutate;48 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override; 49 virtual Statement * mutate( ReturnStmt * returnStmt ) override;47 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 48 49 virtual Statement * mutate( ReturnStmt * returnStmt ); 50 50 51 51 protected: … … 55 55 }; 56 56 57 class CtorDtor final: public GenPoly::PolyMutator {57 class CtorDtor : public GenPoly::PolyMutator { 58 58 public: 59 59 typedef GenPoly::PolyMutator Parent; … … 65 65 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 66 66 67 virtual DeclarationWithType * mutate( ObjectDecl * ) override;68 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;67 virtual DeclarationWithType * mutate( ObjectDecl * ); 68 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 69 69 // should not traverse into any of these declarations to find objects 70 70 // that need to be constructed or destructed 71 virtual Declaration* mutate( StructDecl *aggregateDecl ) override;72 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override{ return aggregateDecl; }73 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override{ return aggregateDecl; }74 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override{ return aggregateDecl; }75 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override{ return typeDecl; }76 virtual Declaration* mutate( TypedefDecl *typeDecl ) override{ return typeDecl; }77 78 virtual Type * mutate( FunctionType *funcType ) override{ return funcType; }79 80 virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override;71 virtual Declaration* mutate( StructDecl *aggregateDecl ); 72 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 73 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 74 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 75 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; } 76 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; } 77 78 virtual Type * mutate( FunctionType *funcType ) { return funcType; } 79 80 virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ); 81 81 82 82 private: … … 91 91 }; 92 92 93 class HoistArrayDimension final: public GenPoly::DeclMutator {93 class HoistArrayDimension : public GenPoly::DeclMutator { 94 94 public: 95 95 typedef GenPoly::DeclMutator Parent; … … 101 101 102 102 private: 103 using Parent::mutate; 104 105 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override; 106 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override; 103 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ); 104 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 107 105 // should not traverse into any of these declarations to find objects 108 106 // that need to be constructed or destructed 109 virtual Declaration* mutate( StructDecl *aggregateDecl ) override{ return aggregateDecl; }110 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override{ return aggregateDecl; }111 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override{ return aggregateDecl; }112 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override{ return aggregateDecl; }113 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override{ return typeDecl; }114 virtual Declaration* mutate( TypedefDecl *typeDecl ) override{ return typeDecl; }115 116 virtual Type* mutate( FunctionType *funcType ) override{ return funcType; }107 virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; } 108 virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 109 virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 110 virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 111 virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; } 112 virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; } 113 114 virtual Type* mutate( FunctionType *funcType ) { return funcType; } 117 115 118 116 void hoist( Type * type ); -
src/InitTweak/InitTweak.h
rf849c8e r837f999 100 100 101 101 class ExpanderImpl; 102 typedef std::list< Expression * > IndexList;103 102 private: 104 103 std::shared_ptr< ExpanderImpl > expander; … … 106 105 107 106 // invariant: list of size 2N (elements come in pairs [index, dimension]) 107 typedef std::list< Expression * > IndexList; 108 108 IndexList indices; 109 109 }; -
src/Makefile.am
rf849c8e r837f999 6 6 ## file "LICENCE" distributed with Cforall. 7 7 ## 8 ## Makefile.am -- 8 ## Makefile.am -- 9 9 ## 10 10 ## Author : Peter A. Buhr 11 11 ## Created On : Sun May 31 08:51:46 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Thu Oct 27 20:41:25201614 ## Update Count : 7 513 ## Last Modified On : Thu Oct 27 11:56:26 2016 14 ## Update Count : 74 15 15 ############################################################################### 16 16 … … 41 41 driver_cfa_cpp_SOURCES = ${SRC} 42 42 driver_cfa_cpp_LDADD = ${LEXLIB} -ldl # yywrap 43 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL -I${abs_top_srcdir}/src/include -DYY_NO_INPUT 44 driver_cfa_cpp_LDFLAGS = -Xlinker -export-dynamic 43 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL -Xlinker -export-dynamic -I${abs_top_srcdir}/src/include 45 44 46 45 MAINTAINERCLEANFILES += ${libdir}/${notdir ${cfa_cpplib_PROGRAMS}} -
src/Makefile.in
rf849c8e r837f999 197 197 driver_cfa_cpp_DEPENDENCIES = $(am__DEPENDENCIES_1) 198 198 driver_cfa_cpp_LINK = $(CXXLD) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) \ 199 $( driver_cfa_cpp_LDFLAGS) $(LDFLAGS) -o $@199 $(AM_LDFLAGS) $(LDFLAGS) -o $@ 200 200 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 201 201 depcomp = $(SHELL) $(top_srcdir)/automake/depcomp … … 417 417 driver_cfa_cpp_SOURCES = ${SRC} 418 418 driver_cfa_cpp_LDADD = ${LEXLIB} -ldl # yywrap 419 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL -I${abs_top_srcdir}/src/include -DYY_NO_INPUT 420 driver_cfa_cpp_LDFLAGS = -Xlinker -export-dynamic 419 driver_cfa_cpp_CXXFLAGS = -Wno-deprecated -Wall -DDEBUG_ALL -Xlinker -export-dynamic -I${abs_top_srcdir}/src/include 421 420 all: $(BUILT_SOURCES) 422 421 $(MAKE) $(AM_MAKEFLAGS) all-am -
src/Parser/ParseNode.h
rf849c8e r837f999 109 109 ExpressionNode * set_extension( bool exten ) { extension = exten; return this; } 110 110 111 v irtual void print( std::ostream &os, int indent = 0 ) const override{}111 void print( std::ostream &os, int indent = 0 ) const {} 112 112 void printOneLine( std::ostream &os, int indent = 0 ) const {} 113 113 … … 187 187 //############################################################################## 188 188 189 structTypeData;189 class TypeData; 190 190 191 191 class DeclarationNode : public ParseNode { … … 271 271 } 272 272 273 v irtual void print( std::ostream &os, int indent = 0 ) const override;274 v irtual void printList( std::ostream &os, int indent = 0 ) const override;273 void print( std::ostream &os, int indent = 0 ) const; 274 void printList( std::ostream &os, int indent = 0 ) const; 275 275 276 276 Declaration * build() const; … … 345 345 virtual StatementNode * append_last_case( StatementNode * ); 346 346 347 virtual void print( std::ostream &os, int indent = 0 ) const override{}348 virtual void printList( std::ostream &os, int indent = 0 ) const override{}347 virtual void print( std::ostream &os, int indent = 0 ) {} 348 virtual void printList( std::ostream &os, int indent = 0 ) {} 349 349 private: 350 350 std::unique_ptr<Statement> stmt; -
src/ResolvExpr/AlternativePrinter.h
rf849c8e r837f999 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // AlternativePrinter.h -- 7 // AlternativePrinter.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 23 23 24 24 namespace ResolvExpr { 25 class AlternativePrinter final: public SymTab::Indexer {25 class AlternativePrinter : public SymTab::Indexer { 26 26 public: 27 27 AlternativePrinter( std::ostream &os ); 28 29 using SymTab::Indexer::visit; 30 virtual void visit( ExprStmt *exprStmt ) override; 28 virtual void visit( ExprStmt *exprStmt ); 31 29 private: 32 30 std::ostream &os; -
src/ResolvExpr/Resolver.cc
rf849c8e r837f999 32 32 33 33 namespace ResolvExpr { 34 class Resolver final: public SymTab::Indexer {34 class Resolver : public SymTab::Indexer { 35 35 public: 36 Resolver() : SymTab::Indexer( false ) {} 37 38 using SymTab::Indexer::visit; 39 virtual void visit( FunctionDecl *functionDecl ) override; 40 virtual void visit( ObjectDecl *functionDecl ) override; 41 virtual void visit( TypeDecl *typeDecl ) override; 42 virtual void visit( EnumDecl * enumDecl ) override; 43 44 virtual void visit( ArrayType * at ) override; 45 virtual void visit( PointerType * at ) override; 46 47 virtual void visit( ExprStmt *exprStmt ) override; 48 virtual void visit( AsmExpr *asmExpr ) override; 49 virtual void visit( AsmStmt *asmStmt ) override; 50 virtual void visit( IfStmt *ifStmt ) override; 51 virtual void visit( WhileStmt *whileStmt ) override; 52 virtual void visit( ForStmt *forStmt ) override; 53 virtual void visit( SwitchStmt *switchStmt ) override; 54 virtual void visit( CaseStmt *caseStmt ) override; 55 virtual void visit( BranchStmt *branchStmt ) override; 56 virtual void visit( ReturnStmt *returnStmt ) override; 57 58 virtual void visit( SingleInit *singleInit ) override; 59 virtual void visit( ListInit *listInit ) override; 60 virtual void visit( ConstructorInit *ctorInit ) override; 36 Resolver() : SymTab::Indexer( false ), switchType( 0 ) {} 37 38 virtual void visit( FunctionDecl *functionDecl ); 39 virtual void visit( ObjectDecl *functionDecl ); 40 virtual void visit( TypeDecl *typeDecl ); 41 virtual void visit( EnumDecl * enumDecl ); 42 43 virtual void visit( ArrayType * at ); 44 virtual void visit( PointerType * at ); 45 46 virtual void visit( ExprStmt *exprStmt ); 47 virtual void visit( AsmExpr *asmExpr ); 48 virtual void visit( AsmStmt *asmStmt ); 49 virtual void visit( IfStmt *ifStmt ); 50 virtual void visit( WhileStmt *whileStmt ); 51 virtual void visit( ForStmt *forStmt ); 52 virtual void visit( SwitchStmt *switchStmt ); 53 virtual void visit( CaseStmt *caseStmt ); 54 virtual void visit( BranchStmt *branchStmt ); 55 virtual void visit( ReturnStmt *returnStmt ); 56 57 virtual void visit( SingleInit *singleInit ); 58 virtual void visit( ListInit *listInit ); 59 virtual void visit( ConstructorInit *ctorInit ); 61 60 private: 62 61 typedef std::list< Initializer * >::iterator InitIterator; … … 70 69 std::list< Type * > functionReturn; 71 70 Type *initContext; 71 Type *switchType; 72 72 bool inEnumDecl = false; 73 73 }; -
src/ResolvExpr/TypeMap.h
rf849c8e r837f999 38 38 typedef typename std::map< std::string, Value* > ValueMap; 39 39 typedef typename ValueMap::iterator ValueMapIterator; 40 40 41 41 Value *voidValue; ///< Value for void type 42 42 Value *basicValue[BasicType::NUMBER_OF_BASIC_TYPES]; ///< Values for basic types … … 54 54 /// One scope of map rollbacks 55 55 typedef std::vector< std::pair< ValueMapIterator, Value* > > MapScope; 56 56 57 57 PointerScope pointers; ///< Value pointers to roll back to their previous state 58 58 MapScope mapNodes; ///< Value map iterators to roll back to their previous state … … 68 68 69 69 std::vector< Rollback > scopes; ///< Scope rollback information 70 70 71 71 struct Lookup : public Visitor { 72 72 Lookup( TypeMap<Value> &typeMap ) : typeMap( typeMap ), found( 0 ), toInsert( 0 ) {} … … 87 87 return found; 88 88 } 89 89 90 90 void findAndReplace( Value *&loc ) { 91 91 found = loc; … … 109 109 } 110 110 } 111 111 112 112 virtual void visit( VoidType *voidType ) { 113 113 findAndReplace( typeMap.voidValue ); 114 114 } 115 115 116 116 virtual void visit( BasicType *basicType ) { 117 117 findAndReplace( typeMap.basicValue[basicType->get_kind()] ); 118 118 } 119 119 120 120 virtual void visit( PointerType *pointerType ) { 121 121 // NOTE This is one of the places where the apporoximation of the resolver is (deliberately) poor; … … 129 129 } 130 130 } 131 131 132 132 virtual void visit( ArrayType *arrayType ) { 133 133 if ( dynamic_cast< FunctionType* >( arrayType->get_base() ) ) { … … 137 137 } 138 138 } 139 139 140 140 virtual void visit( FunctionType *functionType ) { 141 141 findAndReplace( typeMap.functionPointerValue ); 142 142 } 143 143 144 144 virtual void visit( StructInstType *structType ) { 145 145 findAndReplace( typeMap.structValue, structType->get_name() ); 146 146 } 147 147 148 148 virtual void visit( UnionInstType *unionType ) { 149 149 findAndReplace( typeMap.unionValue, unionType->get_name() ); 150 150 } 151 151 152 152 virtual void visit( EnumInstType *enumType ) { 153 153 findAndReplace( typeMap.enumValue, enumType->get_name() ); … … 157 157 Value *found; ///< Value found (NULL if none yet) 158 158 Value *toInsert; ///< Value to insert (NULL if a lookup) 159 }; // structLookup160 friend structLookup;161 159 }; // class Lookup 160 friend class Lookup; 161 162 162 public: 163 163 /// Starts a new scope … … 180 180 scopes.pop_back(); 181 181 } 182 182 183 183 TypeMap() : voidValue( 0 ), pointerValue( 0 ), voidPointerValue( 0 ), functionPointerValue( 0 ), structValue(), unionValue(), enumValue(), scopes() { 184 184 beginScope(); … … 199 199 return searcher.find( key ); 200 200 } 201 201 202 202 }; // class TypeMap 203 203 -
src/ResolvExpr/Unify.cc
rf849c8e r837f999 73 73 const OpenVarSet &openVars; 74 74 WidenMode widenMode; 75 Type *commonType; 75 76 const SymTab::Indexer &indexer; 76 77 }; -
src/SymTab/Validate.cc
rf849c8e r837f999 94 94 95 95 /// Associates forward declarations of aggregates with their definitions 96 class Pass2 final: public Indexer {96 class Pass2 : public Indexer { 97 97 typedef Indexer Parent; 98 98 public: 99 99 Pass2( bool doDebug, const Indexer *indexer ); 100 100 private: 101 using Indexer::visit; 102 void visit( StructInstType *structInst ) final; 103 void visit( UnionInstType *unionInst ) final; 104 void visit( TraitInstType *contextInst ) final; 105 void visit( StructDecl *structDecl ) final; 106 void visit( UnionDecl *unionDecl ) final; 107 void visit( TypeInstType *typeInst ) final; 101 virtual void visit( StructInstType *structInst ); 102 virtual void visit( UnionInstType *unionInst ); 103 virtual void visit( TraitInstType *contextInst ); 104 virtual void visit( StructDecl *structDecl ); 105 virtual void visit( UnionDecl *unionDecl ); 106 virtual void visit( TypeInstType *typeInst ); 108 107 109 108 const Indexer *indexer; … … 183 182 }; 184 183 185 class CompoundLiteral final: public GenPoly::DeclMutator {184 class CompoundLiteral : public GenPoly::DeclMutator { 186 185 DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass; 187 186 188 using GenPoly::DeclMutator::mutate; 189 DeclarationWithType * mutate( ObjectDecl *objectDecl ) final; 190 Expression *mutate( CompoundLiteralExpr *compLitExpr ) final; 187 virtual DeclarationWithType * mutate( ObjectDecl *objectDecl ); 188 virtual Expression *mutate( CompoundLiteralExpr *compLitExpr ); 191 189 }; 192 190 … … 654 652 void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) { 655 653 if ( typedefNames.count( aggDecl->get_name() ) == 0 ) { 656 Type *type = nullptr;654 Type *type; 657 655 if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) { 658 656 type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ); -
src/Tuples/TupleAssignment.cc
rf849c8e r837f999 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // TupleAssignment.cc -- 7 // TupleAssignment.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 29 29 30 30 namespace Tuples { 31 TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder *f )31 TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder *f = 0 ) 32 32 : currentFinder(f), matcher(0), hasMatched( false ) {} 33 33 -
src/Tuples/TupleAssignment.h
rf849c8e r837f999 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // TupleAssignment.h -- 7 // TupleAssignment.h -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 29 29 public: 30 30 // dispatcher for Tuple (multiple and mass) assignment operations 31 TupleAssignSpotter( ResolvExpr::AlternativeFinder * = 0);31 TupleAssignSpotter( ResolvExpr::AlternativeFinder * ); 32 32 ~TupleAssignSpotter() { delete matcher; matcher = 0; } 33 33 … … 97 97 ResolvExpr::AlternativeFinder *currentFinder; 98 98 //std::list<Expression *> rhs, lhs; 99 //Expression *rhs, *lhs;99 Expression *rhs, *lhs; 100 100 Matcher *matcher; 101 101 bool hasMatched; -
src/driver/Makefile.am
rf849c8e r837f999 6 6 ## file "LICENCE" distributed with Cforall. 7 7 ## 8 ## Makefile.am -- 8 ## Makefile.am -- 9 9 ## 10 10 ## Author : Peter A. Buhr … … 26 26 cc1_SOURCES = cc1.cc 27 27 28 cfa.cc : ${abs_top_srcdir}/version29 @true30 31 28 MAINTAINERCLEANFILES = @CFA_PREFIX@/bin/${bin_PROGRAMS} @CFA_PREFIX@/lib/${cc1lib_PROGRAMS} -
src/driver/Makefile.in
rf849c8e r837f999 100 100 CFA_PREFIX = @CFA_PREFIX@ 101 101 CFLAGS = @CFLAGS@ 102 CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@103 102 CPP = @CPP@ 104 103 CPPFLAGS = @CPPFLAGS@ … … 543 542 544 543 545 cfa.cc : ${abs_top_srcdir}/version546 @true547 548 544 # Tell versions [3.59,3.63) of GNU make to not export all variables. 549 545 # Otherwise a system limit (for SysV at least) may be exceeded. -
src/driver/cfa.cc
rf849c8e r837f999 25 25 using std::endl; 26 26 using std::string; 27 using std::to_string;28 27 29 28 … … 51 50 52 51 int main( int argc, char *argv[] ) { 53 string Version( CFA_VERSION_LONG); // current version number from CONFIG54 string Major( to_string( CFA_VERSION_MAJOR ) ), Minor( to_string( CFA_VERSION_MINOR ) ), Patch( to_string( CFA_VERSION_PATCH ));52 string Version( VERSION ); // current version number from CONFIG 53 string Major( CFA_VERSION_MAJOR ), Minor( CFA_VERSION_MINOR ), Patch( CFA_VERSION_MINOR ); 55 54 56 55 string installincdir( CFA_INCDIR ); // fixed location of include files -
src/examples/Makefile.in
rf849c8e r837f999 111 111 # applies to both programs 112 112 CFLAGS = -g -Wall -Wno-unused-function # TEMPORARY: does not build with -O2 113 CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@114 113 CPP = @CPP@ 115 114 CPPFLAGS = @CPPFLAGS@ -
src/libcfa/Makefile.in
rf849c8e r837f999 137 137 CFA_PREFIX = @CFA_PREFIX@ 138 138 CFLAGS = -quiet -no-include-stdhdr -g -Wall -Wno-unused-function @CFA_FLAGS@ -B${abs_top_srcdir}/src/driver -XCFA -t # TEMPORARY: does not build with -O2 139 CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@140 139 CPP = @CPP@ 141 140 CPPFLAGS = @CPPFLAGS@ -
src/tests/Makefile.in
rf849c8e r837f999 121 121 # applies to both programs 122 122 CFLAGS = -g -Wall -Wno-unused-function @CFA_FLAGS@ # TEMPORARY: does not build with -O2 123 CONFIG_STATUS_DEPENDENCIES = @CONFIG_STATUS_DEPENDENCIES@124 123 CPP = @CPP@ 125 124 CPPFLAGS = @CPPFLAGS@
Note:
See TracChangeset
for help on using the changeset viewer.