Changeset 99cadc60


Ignore:
Timestamp:
Jul 31, 2019, 3:26:06 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
61cfae2
Parents:
c60a664 (diff), 40287c8 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
1 added
1 deleted
31 edited

Legend:

Unmodified
Added
Removed
  • automake/cfa.m4

    rc60a664 r99cadc60  
    6666                "x86-64"     ) cannon_arch_name="x64";;
    6767                "x86_64"     ) cannon_arch_name="x64";;
     68                "aarch64"    ) cannon_arch_name="x64";;
    6869                "x86"        ) cannon_arch_name="x86";;
    6970                "i386"       ) cannon_arch_name="x86";;
     
    7576                "armv7l"     ) cannon_arch_name="arm";;
    7677                *)
    77                 >&2 echo "Unkown architecture " $arch_name;
     78                >&2 echo "Unknown architecture " $arch_name;
    7879                exit 1
    7980                ;;
  • benchmark/Makefile.am

    rc60a664 r99cadc60  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Mon Jun 24 16:45:42 2019
    14 ## Update Count     : 53
     13## Last Modified On : Mon Jul 29 18:02:19 2019
     14## Update Count     : 54
    1515###############################################################################
    1616
     
    5050REPEAT   = ${abs_top_builddir}/tools/repeat
    5151STATS    = ${abs_top_srcdir}/tools/stat.py
    52 repeats  = 3 # 30
     52# NEED AT LEAST 4 DATA VALUES FOR BENCHMARKS BECAUSE THE MAX AND MIN VALUES ARE REMOVED
     53repeats  = 5 # 31 for benchmarks
    5354skipcompile = no
    5455TIME_FORMAT = "%E"
  • benchmark/creation/JavaThread.java

    rc60a664 r99cadc60  
    11public class JavaThread {
     2        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
     3        // Bijective   
     4        // Cycle length for non-zero values is 4G-1.
     5        // 0 is absorbing and should be avoided -- fixed point.
     6        // The returned value is typically masked to produce a positive value.
     7        static volatile int Ticket = 0 ;
     8
     9        private static int nextRandom (int x) {
     10                if (x == 0) {
     11                        // reseed the PRNG
     12                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     13                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     14                        // If the race is a concern switch to an AtomicInteger. 
     15                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     16                        // (readily) predictable at compile-time so the JIT will not be able to elide
     17                        // nextRandom() invocations. 
     18                        x = ++Ticket ;
     19                        if (x == 0) x = 1 ;
     20                }
     21                x ^= x << 6;
     22                x ^= x >>> 21;
     23                x ^= x << 7;
     24                return x ;   
     25        }
     26        static int x = 2;
     27
     28        static private final int NoOfTimes = Integer.parseInt("10000") ;
     29
    230        public static class MyThread extends Thread {
    331                @Override
    432                public void run() {}
    533        }
    6 
    7         public static void main(String[] args) throws InterruptedException {
    8                 int NoOfTimes = 50000;
    9                 long start = System.nanoTime();
     34        public static void helper() throws InterruptedException {
    1035                for(int i = 1; i <= NoOfTimes; i += 1) {
    11                         JavaThread.MyThread m = new JavaThread.MyThread();
    12                         m.start();
     36                        MyThread m = new MyThread();
     37                        x = nextRandom( x );
     38                        m.start();
    1339                        m.join();
    1440                }
     41        }
     42        public static void InnerMain() throws InterruptedException {
     43                long start = System.nanoTime();
     44                helper();
    1545                long end = System.nanoTime();
    16                 System.out.println( (end - start) / NoOfTimes);
     46                System.out.println( (end - start) / NoOfTimes );
     47        }
     48        public static void main(String[] args) throws InterruptedException {
     49                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
     50                        InnerMain();
     51                        Thread.sleep(2000);     // 2 seconds
     52                        x = nextRandom(x);
     53                }
     54                if ( x == 0 ) System.out.println(x);
    1755        }
    1856}
  • benchmark/ctxswitch/JavaThread.java

    rc60a664 r99cadc60  
    11public class JavaThread {
    2         public static void main(String[] args) {
    3                 int NoOfTimes = 5000000;
    4                 long start = System.nanoTime();
     2        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
     3        // Bijective   
     4        // Cycle length for non-zero values is 4G-1.
     5        // 0 is absorbing and should be avoided -- fixed point.
     6        // The returned value is typically masked to produce a positive value.
     7        static volatile int Ticket = 0 ;
     8
     9        private static int nextRandom (int x) {
     10                if (x == 0) {
     11                        // reseed the PRNG
     12                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     13                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     14                        // If the race is a concern switch to an AtomicInteger. 
     15                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     16                        // (readily) predictable at compile-time so the JIT will not be able to elide
     17                        // nextRandom() invocations. 
     18                        x = ++Ticket ;
     19                        if (x == 0) x = 1 ;
     20                }
     21                x ^= x << 6;
     22                x ^= x >>> 21;
     23                x ^= x << 7;
     24                return x ;   
     25        }
     26        static int x = 2;
     27
     28        static private final int NoOfTimes = Integer.parseInt("1000000") ;
     29
     30        public static void helper() {
    531                for(int i = 1; i <= NoOfTimes; i += 1) {
    632                        Thread.yield();
    733                }
     34        }
     35        public static void InnerMain() {
     36                long start = System.nanoTime();
     37                helper();
    838                long end = System.nanoTime();
    9                 System.out.println( (end - start) / NoOfTimes);
     39                System.out.println( (end - start) / NoOfTimes );
     40        }
     41        public static void main(String[] args) throws InterruptedException {
     42                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
     43                        InnerMain();
     44                        Thread.sleep(2000);     // 2 seconds
     45                        x = nextRandom(x);
     46                }
     47                if ( x == 0 ) System.out.println(x);
    1048        }
    1149}
  • benchmark/mutex/JavaThread.java

    rc60a664 r99cadc60  
    11public class JavaThread {
    2         public synchronized void noop() {}
     2        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
     3        // Bijective   
     4        // Cycle length for non-zero values is 4G-1.
     5        // 0 is absorbing and should be avoided -- fixed point.
     6        // The returned value is typically masked to produce a positive value.
     7        static volatile int Ticket = 0 ;
    38
    4         public static void main(String[] args) {
    5                 int NoOfTimes = 5000000;
     9        private static int nextRandom (int x) {
     10                if (x == 0) {
     11                        // reseed the PRNG
     12                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     13                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     14                        // If the race is a concern switch to an AtomicInteger. 
     15                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     16                        // (readily) predictable at compile-time so the JIT will not be able to elide
     17                        // nextRandom() invocations. 
     18                        x = ++Ticket ;
     19                        if (x == 0) x = 1 ;
     20                }
     21                x ^= x << 6;
     22                x ^= x >>> 21;
     23                x ^= x << 7;
     24                return x ;   
     25        }
     26        static int x = 2;
     27
     28        static private final int NoOfTimes = Integer.parseInt("100000000") ;
     29
     30        public synchronized void noop() {
     31                x = nextRandom( x );
     32        }
     33        public static void helper() throws InterruptedException {
    634                JavaThread j = new JavaThread();
    7                 long start = System.nanoTime();
     35                // Inhibit biased locking ...
     36                x = (j.hashCode() ^ System.identityHashCode(j)) | 1 ;     
    837                for(int i = 1; i <= NoOfTimes; i += 1) {
     38                        x = nextRandom(x);
    939                        j.noop();
    1040                }
     41        }
     42        public static void InnerMain() throws InterruptedException {
     43                long start = System.nanoTime();
     44                helper();
    1145                long end = System.nanoTime();
    12                 System.out.println( (end - start) / NoOfTimes);
     46                System.out.println( (end - start) / NoOfTimes );
     47        }
     48        public static void main(String[] args) throws InterruptedException {
     49                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
     50                        InnerMain();
     51                        Thread.sleep(2000);     // 2 seconds
     52                        x = nextRandom(x);
     53                }
     54                if ( x == 0 ) System.out.println(x);
    1355        }
    1456}
  • benchmark/schedint/JavaThread.java

    rc60a664 r99cadc60  
    11class Monitor {
    22        public static volatile Boolean go = false;
     3        public static volatile Boolean next = false;
    34}
    45
     
    1314                while( Monitor.go ) {
    1415                        synchronized(this.m) {
     16                                Monitor.next = false;
    1517                                this.m.notify();
    1618                        }
     19                        while( ! Monitor.next && Monitor.go );  // spin until woken
    1720                }
    1821        }
     
    2023
    2124public class JavaThread {
    22         public static void main(String[] args) throws InterruptedException {
    23                 int NoOfTimes = 50000;
     25        // Simplistic low-quality Marsaglia Shift-XOR pseudo-random number generator.
     26        // Bijective   
     27        // Cycle length for non-zero values is 4G-1.
     28        // 0 is absorbing and should be avoided -- fixed point.
     29        // The returned value is typically masked to produce a positive value.
     30        static volatile int Ticket = 0 ;
     31
     32        private static int nextRandom (int x) {
     33                if (x == 0) {
     34                        // reseed the PRNG
     35                        // Ticket is accessed infrequently and does not constitute a coherence hot-spot.
     36                        // Note that we use a non-atomic racy increment -- the race is rare and benign.
     37                        // If the race is a concern switch to an AtomicInteger. 
     38                        // In addition accesses to the RW volatile global "Ticket"  variable are not
     39                        // (readily) predictable at compile-time so the JIT will not be able to elide
     40                        // nextRandom() invocations. 
     41                        x = ++Ticket ;
     42                        if (x == 0) x = 1 ;
     43                }
     44                x ^= x << 6;
     45                x ^= x >>> 21;
     46                x ^= x << 7;
     47                return x ;   
     48        }
     49        static int x = 2;
     50
     51        static private final int NoOfTimes = Integer.parseInt("1000000") ;
     52
     53        public static void helper( Monitor m ) throws InterruptedException {
     54                for(int i = 1; i <= NoOfTimes; i += 1) {
     55                        m.wait();               // relase monitor lock
     56                        m.next = true;
     57                }
     58        }
     59        public static void InnerMain() throws InterruptedException {
    2460                Monitor m = new Monitor();
    2561                long start, end;
     
    3167                        }
    3268                        start = System.nanoTime();
    33                         for(int i = 1; i <= NoOfTimes; i += 1) {
    34                                 m.wait();
    35                         }
     69                        helper( m );
    3670                        end = System.nanoTime();
    3771                }
     
    4074                System.out.println( (end - start) / NoOfTimes);
    4175        }
     76        public static void main(String[] args) throws InterruptedException {
     77                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
     78                        InnerMain();
     79                        Thread.sleep(2000);     // 2 seconds
     80                        x = nextRandom(x);
     81                }
     82                if ( x == 0 ) System.out.println(x);
     83        }
    4284}
  • configure

    rc60a664 r99cadc60  
    34333433                "x86-64"     ) cannon_arch_name="x64";;
    34343434                "x86_64"     ) cannon_arch_name="x64";;
     3435                "aarch64"    ) cannon_arch_name="x64";;
    34353436                "x86"        ) cannon_arch_name="x86";;
    34363437                "i386"       ) cannon_arch_name="x86";;
     
    34423443                "armv7l"     ) cannon_arch_name="arm";;
    34433444                *)
    3444                 >&2 echo "Unkown architecture " $arch_name;
     3445                >&2 echo "Unknown architecture " $arch_name;
    34453446                exit 1
    34463447                ;;
     
    34743475                "x86-64"     ) cannon_arch_name="x64";;
    34753476                "x86_64"     ) cannon_arch_name="x64";;
     3477                "aarch64"    ) cannon_arch_name="x64";;
    34763478                "x86"        ) cannon_arch_name="x86";;
    34773479                "i386"       ) cannon_arch_name="x86";;
     
    34833485                "armv7l"     ) cannon_arch_name="arm";;
    34843486                *)
    3485                 >&2 echo "Unkown architecture " $arch_name;
     3487                >&2 echo "Unknown architecture " $arch_name;
    34863488                exit 1
    34873489                ;;
  • doc/papers/concurrency/Paper.tex

    rc60a664 r99cadc60  
    307307In many ways, \CFA is to C as Scala~\cite{Scala} is to Java, providing a \emph{research vehicle} for new typing and control-flow capabilities on top of a highly popular programming language allowing immediate dissemination.
    308308Within the \CFA framework, new control-flow features are created from scratch because ISO \Celeven defines only a subset of the \CFA extensions, where the overlapping features are concurrency~\cite[\S~7.26]{C11}.
    309 However, \Celeven concurrency is largely wrappers for a subset of the pthreads library~\cite{Butenhof97,Pthreads}, and \Celeven and pthreads concurrency is simple, based on thread fork/join in a function and a few locks, which is low-level and error-prone;
     309However, \Celeven concurrency is largely wrappers for a subset of the pthreads library~\cite{Butenhof97,Pthreads}, and \Celeven and pthreads concurrency is simple, based on thread fork/join in a function and mutex/condition locks, which is low-level and error-prone;
    310310no high-level language concurrency features are defined.
    311 Interestingly, almost a decade after publication of the \Celeven standard, neither gcc-8, clang-9 nor msvc-19 (most recent versions) support the \Celeven include @threads.h@, indicating little interest in the C11 concurrency approach.
     311Interestingly, almost a decade after publication of the \Celeven standard, neither gcc-8, clang-9 nor msvc-19 (most recent versions) support the \Celeven include @threads.h@, indicating little interest in the C11 concurrency approach (possibly because the effort to add concurrency to \CC).
    312312Finally, while the \Celeven standard does not state a threading model, the historical association with pthreads suggests implementations would adopt kernel-level threading (1:1)~\cite{ThreadModel}.
    313313
     
    333333
    334334Finally, it is important for a language to provide safety over performance \emph{as the default}, allowing careful reduction of safety for performance when necessary.
    335 Two concurrency violations of this philosophy are \emph{spurious wakeup} (random wakeup~\cite[\S~8]{Buhr05a}) and \emph{barging} (signals-as-hints~\cite[\S~8]{Buhr05a}), where one is a consequence of the other, \ie once there is spurious wakeup, signals-as-hints follow.
     335Two concurrency violations of this philosophy are \emph{spurious wakeup} (random wakeup~\cite[\S~8]{Buhr05a}) and \emph{barging}\footnote{
     336The notion of competitive succession instead of direct handoff, \ie a lock owner releases the lock and an arriving thread acquires it ahead of preexisting waiter threads.
     337} (signals-as-hints~\cite[\S~8]{Buhr05a}), where one is a consequence of the other, \ie once there is spurious wakeup, signals-as-hints follow.
    336338However, spurious wakeup is \emph{not} a foundational concurrency property~\cite[\S~8]{Buhr05a}, it is a performance design choice.
    337339Similarly, signals-as-hints are often a performance decision.
     
    351353We present comparative examples so the reader can judge if the \CFA control-flow extensions are better and safer than those in other concurrent, imperative programming languages, and perform experiments to show the \CFA runtime is competitive with other similar mechanisms.
    352354The main contributions of this work are:
    353 \begin{itemize}
     355\begin{itemize}[topsep=3pt,itemsep=1pt]
    354356\item
    355357language-level generators, coroutines and user-level threading, which respect the expectations of C programmers.
     
    370372\end{itemize}
    371373
     374Section~\ref{s:StatefulFunction} begins advanced control by introducing sequential functions that retain data and execution state between calls, which produces constructs @generator@ and @coroutine@.
     375Section~\ref{s:Concurrency} begins concurrency, or how to create (fork) and destroy (join) a thread, which produces the @thread@ construct.
     376Section~\ref{s:MutualExclusionSynchronization} discusses the two mechanisms to restricted nondeterminism when controlling shared access to resources (mutual exclusion) and timing relationships among threads (synchronization).
     377Section~\ref{s:Monitor} shows how both mutual exclusion and synchronization are safely embedded in the @monitor@ and @thread@ constructs.
     378Section~\ref{s:CFARuntimeStructure} describes the large-scale mechanism to structure (cluster) threads and virtual processors (kernel threads).
     379Section~\ref{s:Performance} uses a series of microbenchmarks to compare \CFA threading with pthreads, Java OpenJDK-9, Go 1.12.6 and \uC 7.0.0.
     380
    372381
    373382\section{Stateful Function}
     383\label{s:StatefulFunction}
    374384
    375385The stateful function is an old idea~\cite{Conway63,Marlin80} that is new again~\cite{C++20Coroutine19}, where execution is temporarily suspended and later resumed, \eg plugin, device driver, finite-state machine.
     
    617627Figure~\ref{f:CFibonacciSim} shows the C implementation of the \CFA generator only needs one additional field, @next@, to handle retention of execution state.
    618628The computed @goto@ at the start of the generator main, which branches after the previous suspend, adds very little cost to the resume call.
    619 Finally, an explicit generator type provides both design and performance benefits, such as multiple type-safe interface functions taking and returning arbitrary types.
     629Finally, an explicit generator type provides both design and performance benefits, such as multiple type-safe interface functions taking and returning arbitrary types.\footnote{
     630The \CFA operator syntax uses \lstinline|?| to denote operands, which allows precise definitions for pre, post, and infix operators, \eg \lstinline|++?|, \lstinline|?++|, and \lstinline|?+?|, in addition \lstinline|?\{\}| denotes a constructor, as in \lstinline|foo `f` = `\{`...`\}`|, \lstinline|^?\{\}| denotes a destructor, and \lstinline|?()| is \CC function call \lstinline|operator()|.
     631}%
    620632\begin{cfa}
    621633int ?()( Fib & fib ) { return `resume( fib )`.fn; } $\C[3.9in]{// function-call interface}$
     
    15111523
    15121524\section{Mutual Exclusion / Synchronization}
     1525\label{s:MutualExclusionSynchronization}
    15131526
    15141527Unrestricted nondeterminism is meaningless as there is no way to know when the result is completed without synchronization.
     
    15511564higher-level mechanisms often simplify usage by adding better coupling between synchronization and data, \eg receive-specific versus receive-any thread in message passing or offering specialized solutions, \eg barrier lock.
    15521565Often synchronization is used to order access to a critical section, \eg ensuring a waiting writer thread enters the critical section before a calling reader thread.
    1553 If the calling reader is scheduled before the waiting writer, the reader has \newterm{barged}.
     1566If the calling reader is scheduled before the waiting writer, the reader has barged.
    15541567Barging can result in staleness/freshness problems, where a reader barges ahead of a writer and reads temporally stale data, or a writer barges ahead of another writer overwriting data with a fresh value preventing the previous value from ever being read (lost computation).
    15551568Preventing or detecting barging is an involved challenge with low-level locks, which is made easier through higher-level constructs.
     
    21202133
    21212134
    2122 \subsection{Extended \protect\lstinline@waitfor@}
    2123 
    2124 Figure~\ref{f:ExtendedWaitfor} show the extended form of the @waitfor@ statement to conditionally accept one of a group of mutex functions, with an optional statement to be performed \emph{after} the mutex function finishes.
     2135\subsection{\texorpdfstring{Extended \protect\lstinline@waitfor@}{Extended waitfor}}
     2136
     2137Figure~\ref{f:ExtendedWaitfor} shows the extended form of the @waitfor@ statement to conditionally accept one of a group of mutex functions, with an optional statement to be performed \emph{after} the mutex function finishes.
    21252138For a @waitfor@ clause to be executed, its @when@ must be true and an outstanding call to its corresponding member(s) must exist.
    21262139The \emph{conditional-expression} of a @when@ may call a function, but the function must not block or context switch.
     
    21312144Hence, the terminating @else@ clause allows a conditional attempt to accept a call without blocking.
    21322145If both @timeout@ and @else@ clause are present, the @else@ must be conditional, or the @timeout@ is never triggered.
     2146There is also a traditional future wait queue (not shown) (\eg Microsoft (@WaitForMultipleObjects@)), to wait for a specified number of future elements in the queue.
    21332147
    21342148\begin{figure}
     
    23552369
    23562370
    2357 \subsection{\protect\lstinline@mutex@ Threads}
     2371\subsection{\texorpdfstring{\protect\lstinline@mutex@ Threads}{mutex Threads}}
    23582372
    23592373Threads in \CFA can also be monitors to allow \emph{direct communication} among threads, \ie threads can have mutex functions that are called by other threads.
     
    24992513\renewcommand{\arraystretch}{1.25}
    25002514%\setlength{\tabcolsep}{5pt}
    2501 \begin{tabular}{c|c|l|l}
    2502 \multicolumn{2}{c|}{object properties} & \multicolumn{2}{c}{mutual exclusion} \\
     2515\begin{tabular}{c|c||l|l}
     2516\multicolumn{2}{c||}{object properties} & \multicolumn{2}{c}{mutual exclusion} \\
    25032517\hline
    25042518thread  & stateful                              & \multicolumn{1}{c|}{No} & \multicolumn{1}{c}{Yes} \\
     
    26052619
    26062620
    2607 \section{\protect\CFA Runtime Structure}
     2621\section{Runtime Structure}
    26082622\label{s:CFARuntimeStructure}
    26092623
     
    27092723
    27102724\section{Performance}
    2711 \label{results}
     2725\label{s:Performance}
    27122726
    27132727To verify the implementation of the \CFA runtime, a series of microbenchmarks are performed comparing \CFA with pthreads, Java OpenJDK-9, Go 1.12.6 and \uC 7.0.0.
     
    27152729The benchmark computer is an AMD Opteron\texttrademark\ 6380 NUMA 64-core, 8 socket, 2.5 GHz processor, running Ubuntu 16.04.6 LTS, and \CFA/\uC are compiled with gcc 6.5.
    27162730
    2717 All benchmarks are run using the following harness.
     2731All benchmarks are run using the following harness. (The Java harness is augmented to circumvent JIT issues.)
    27182732\begin{cfa}
    27192733unsigned int N = 10_000_000;
     
    27542768\begin{tabular}[t]{@{}r*{3}{D{.}{.}{5.2}}@{}}
    27552769\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2756 \CFA Coroutine Lazy             & 14.3          & 14.3          & 0.32          \\
    2757 \CFA Coroutine Eager    & 522.8         & 525.3         & 5.81          \\
    2758 \CFA Thread                             & 1257.8        & 1291.2        & 86.19         \\
    2759 \uC Coroutine                   & 92.2          & 91.4          & 1.58          \\
    2760 \uC Thread                              & 499.5         & 500.1         & 5.67          \\
    2761 Goroutine                               & 4397.0        & 4362.8        & 390.77        \\
    2762 Java Thread                             & 107405.0      & 107794.8      & 1601.33       \\
    2763 % Qthreads                              & 159.9         & 159.6         & 0.73          \\
    2764 Pthreads                                & 32920.9       & 32882.7       & 213.55
     2770\CFA Coroutine Lazy             & 13.2          & 13.1          & 0.44          \\
     2771\CFA Coroutine Eager    & 531.3         & 536.0         & 26.54         \\
     2772\CFA Thread                             & 2074.9        & 2066.5        & 170.76        \\
     2773\uC Coroutine                   & 89.6          & 90.5          & 1.83          \\
     2774\uC Thread                              & 528.2         & 528.5         & 4.94          \\
     2775Goroutine                               & 4068.0        & 4113.1        & 414.55        \\
     2776Java Thread                             & 103848.5      & 104295.4      & 2637.57       \\
     2777Pthreads                                & 33112.6       & 33127.1       & 165.90
     2778\end{tabular}
     2779\end{multicols}
     2780
     2781
     2782\paragraph{Context-Switching}
     2783
     2784In procedural programming, the cost of a function call is important as modularization (refactoring) increases.
     2785(In many cases, a compiler inlines function calls to eliminate this cost.)
     2786Similarly, when modularization extends to coroutines/tasks, the time for a context switch becomes a relevant factor.
     2787The coroutine test is from resumer to suspender and from suspender to resumer, which is two context switches.
     2788The thread test is using yield to enter and return from the runtime kernel, which is two context switches.
     2789The difference in performance between coroutine and thread context-switch is the cost of scheduling for threads, whereas coroutines are self-scheduling.
     2790Figure~\ref{f:ctx-switch} only shows the \CFA code for coroutines/threads (other systems are similar) with all results in Table~\ref{tab:ctx-switch}.
     2791
     2792\begin{multicols}{2}
     2793\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     2794\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     2795@coroutine@ C {} c;
     2796void main( C & ) { for ( ;; ) { @suspend;@ } }
     2797int main() { // coroutine test
     2798        BENCH( for ( N ) { @resume( c );@ } )
     2799        sout | result`ns;
     2800}
     2801int main() { // task test
     2802        BENCH( for ( N ) { @yield();@ } )
     2803        sout | result`ns;
     2804}
     2805\end{cfa}
     2806\captionof{figure}{\CFA context-switch benchmark}
     2807\label{f:ctx-switch}
     2808
     2809\columnbreak
     2810
     2811\vspace*{-16pt}
     2812\captionof{table}{Context switch comparison (nanoseconds)}
     2813\label{tab:ctx-switch}
     2814\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
     2815\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     2816C function              & 1.8   & 1.8   & 0.01  \\
     2817\CFA generator  & 2.4   & 2.2   & 0.25  \\
     2818\CFA Coroutine  & 36.2  & 36.2  & 0.25  \\
     2819\CFA Thread             & 93.2  & 93.5  & 2.09  \\
     2820\uC Coroutine   & 52.0  & 52.1  & 0.51  \\
     2821\uC Thread              & 96.2  & 96.3  & 0.58  \\
     2822Goroutine               & 141.0 & 141.3 & 3.39  \\
     2823Java Thread             & 374.0 & 375.8 & 10.38 \\
     2824Pthreads Thread & 361.0 & 365.3 & 13.19
     2825\end{tabular}
     2826\end{multicols}
     2827
     2828
     2829\paragraph{Mutual-Exclusion}
     2830
     2831Uncontented mutual exclusion, which frequently occurs, is measured by entering/leaving a critical section.
     2832For monitors, entering and leaving a monitor function is measured.
     2833To put the results in context, the cost of entering a non-inline function and the cost of acquiring and releasing a @pthread_mutex@ lock is also measured.
     2834Figure~\ref{f:mutex} shows the code for \CFA with all results in Table~\ref{tab:mutex}.
     2835Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
     2836
     2837\begin{multicols}{2}
     2838\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     2839\begin{cfa}
     2840@monitor@ M {} m1/*, m2, m3, m4*/;
     2841void __attribute__((noinline))
     2842do_call( M & @mutex m/*, m2, m3, m4*/@ ) {}
     2843int main() {
     2844        BENCH(
     2845                for( N ) do_call( m1/*, m2, m3, m4*/ );
     2846        )
     2847        sout | result`ns;
     2848}
     2849\end{cfa}
     2850\captionof{figure}{\CFA acquire/release mutex benchmark}
     2851\label{f:mutex}
     2852
     2853\columnbreak
     2854
     2855\vspace*{-16pt}
     2856\captionof{table}{Mutex comparison (nanoseconds)}
     2857\label{tab:mutex}
     2858\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
     2859\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     2860test and test-and-test lock             & 19.1  & 18.9  & 0.40  \\
     2861\CFA @mutex@ function, 1 arg.   & 45.9  & 46.6  & 1.45  \\
     2862\CFA @mutex@ function, 2 arg.   & 105.0 & 104.7 & 3.08  \\
     2863\CFA @mutex@ function, 4 arg.   & 165.0 & 167.6 & 5.65  \\
     2864\uC @monitor@ member rtn.               & 54.0  & 53.7  & 0.82  \\
     2865Java synchronized method                & 31.0  & 31.1  & 0.50  \\
     2866Pthreads Mutex Lock                             & 33.6  & 32.6  & 1.14
     2867\end{tabular}
     2868\end{multicols}
     2869
     2870
     2871\paragraph{External Scheduling}
     2872
     2873External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement.
     2874Figure~\ref{f:ext-sched} shows the code for \CFA, with results in Table~\ref{tab:ext-sched}.
     2875Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
     2876
     2877\begin{multicols}{2}
     2878\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     2879\vspace*{-16pt}
     2880\begin{cfa}
     2881volatile int go = 0;
     2882@monitor@ M {} m;
     2883thread T {};
     2884void __attribute__((noinline))
     2885do_call( M & @mutex@ ) {}
     2886void main( T & ) {
     2887        while ( go == 0 ) { yield(); }
     2888        while ( go == 1 ) { do_call( m ); }
     2889}
     2890int __attribute__((noinline))
     2891do_wait( M & @mutex@ m ) {
     2892        go = 1; // continue other thread
     2893        BENCH( for ( N ) { @waitfor( do_call, m );@ } )
     2894        go = 0; // stop other thread
     2895        sout | result`ns;
     2896}
     2897int main() {
     2898        T t;
     2899        do_wait( m );
     2900}
     2901\end{cfa}
     2902\captionof{figure}{\CFA external-scheduling benchmark}
     2903\label{f:ext-sched}
     2904
     2905\columnbreak
     2906
     2907\vspace*{-16pt}
     2908\captionof{table}{External-scheduling comparison (nanoseconds)}
     2909\label{tab:ext-sched}
     2910\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
     2911\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     2912\CFA @waitfor@, 1 @monitor@     & 376.4 & 376.8 & 7.63  \\
     2913\CFA @waitfor@, 2 @monitor@     & 491.4 & 492.0 & 13.31 \\
     2914\CFA @waitfor@, 4 @monitor@     & 681.0 & 681.7 & 19.10 \\
     2915\uC @_Accept@                           & 331.1 & 331.4 & 2.66
    27652916\end{tabular}
    27662917\end{multicols}
     
    28102961\begin{tabular}{@{}r*{3}{D{.}{.}{5.2}}@{}}
    28112962\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2812 \CFA @signal@, 1 @monitor@      & 367.0         & 371.5         & 17.34         \\
    2813 \CFA @signal@, 2 @monitor@      & 477.2         & 478.6         & 8.31          \\
    2814 \CFA @signal@, 4 @monitor@      & 725.8         & 734.0         & 17.98         \\
    2815 \uC @signal@                            & 322.8         & 323.0         & 3.64          \\
    2816 Java @notify@                           & 16520.0       & 20096.7       & 9378.53       \\
    2817 Pthreads Cond. Variable         & 4931.3        & 5057.0        & 326.80
    2818 \end{tabular}
    2819 \end{multicols}
    2820 
    2821 
    2822 \paragraph{External Scheduling}
    2823 
    2824 External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement.
    2825 Figure~\ref{f:ext-sched} shows the code for \CFA, with results in Table~\ref{tab:ext-sched}.
    2826 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    2827 
    2828 \begin{multicols}{2}
    2829 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2830 \vspace*{-16pt}
    2831 \begin{cfa}
    2832 volatile int go = 0;
    2833 @monitor@ M {} m;
    2834 thread T {};
    2835 void __attribute__((noinline))
    2836 do_call( M & @mutex@ ) {}
    2837 void main( T & ) {
    2838         while ( go == 0 ) { yield(); }
    2839         while ( go == 1 ) { do_call( m ); }
    2840 }
    2841 int __attribute__((noinline))
    2842 do_wait( M & @mutex@ m ) {
    2843         go = 1; // continue other thread
    2844         BENCH( for ( N ) { @waitfor( do_call, m );@ } )
    2845         go = 0; // stop other thread
    2846         sout | result`ns;
    2847 }
    2848 int main() {
    2849         T t;
    2850         do_wait( m );
    2851 }
    2852 \end{cfa}
    2853 \captionof{figure}{\CFA external-scheduling benchmark}
    2854 \label{f:ext-sched}
    2855 
    2856 \columnbreak
    2857 
    2858 \vspace*{-16pt}
    2859 \captionof{table}{External-scheduling comparison (nanoseconds)}
    2860 \label{tab:ext-sched}
    2861 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    2862 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2863 \CFA @waitfor@, 1 @monitor@     & 366.7         & 369.5 & 7.52  \\
    2864 \CFA @waitfor@, 2 @monitor@     & 453.6         & 455.8 & 12.38 \\
    2865 \CFA @waitfor@, 4 @monitor@     & 671.6         & 672.4 & 14.16 \\
    2866 \uC @_Accept@                           & 336.0         & 335.8         & 3.22
    2867 \end{tabular}
    2868 \end{multicols}
    2869 
    2870 
    2871 \paragraph{Context-Switching}
    2872 
    2873 In procedural programming, the cost of a function call is important as modularization (refactoring) increases.
    2874 (In many cases, a compiler inlines function calls to eliminate this cost.)
    2875 Similarly, when modularization extends to coroutines/tasks, the time for a context switch becomes a relevant factor.
    2876 The coroutine test is from resumer to suspender and from suspender to resumer, which is two context switches.
    2877 The thread test is using yield to enter and return from the runtime kernel, which is two context switches.
    2878 The difference in performance between coroutine and thread context-switch is the cost of scheduling for threads, whereas coroutines are self-scheduling.
    2879 Figure~\ref{f:ctx-switch} only shows the \CFA code for coroutines/threads (other systems are similar) with all results in Table~\ref{tab:ctx-switch}.
    2880 
    2881 \begin{multicols}{2}
    2882 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2883 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    2884 @coroutine@ C {} c;
    2885 void main( C & ) { for ( ;; ) { @suspend;@ } }
    2886 int main() { // coroutine test
    2887         BENCH( for ( N ) { @resume( c );@ } )
    2888         sout | result`ns;
    2889 }
    2890 int main() { // task test
    2891         BENCH( for ( N ) { @yield();@ } )
    2892         sout | result`ns;
    2893 }
    2894 \end{cfa}
    2895 \captionof{figure}{\CFA context-switch benchmark}
    2896 \label{f:ctx-switch}
    2897 
    2898 \columnbreak
    2899 
    2900 \vspace*{-16pt}
    2901 \captionof{table}{Context switch comparison (nanoseconds)}
    2902 \label{tab:ctx-switch}
    2903 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    2904 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2905 C function              & 1.8           & 1.8   & 0             \\
    2906 \CFA generator  & 2.7           & 2.4   & 0.27  \\
    2907 \CFA Coroutine  & 37.8          & 37.7  & 0.22  \\
    2908 \CFA Thread             & 93.6          & 93.8  & 1.46  \\
    2909 \uC Coroutine   & 52.7          & 52.8  & 0.28  \\
    2910 \uC Thread              & 93.4          & 93.7  & 1.04  \\
    2911 Goroutine               & 140.0         & 139.7 & 2.93  \\
    2912 Java Thread             & 374.0         & 375.8 & 10.38 \\
    2913 % Qthreads Thread       & 159.5         & 159.3 & 0.71  \\
    2914 Pthreads Thread & 334.4         & 335.0 & 1.95  \\
    2915 \end{tabular}
    2916 \end{multicols}
    2917 
    2918 
    2919 \paragraph{Mutual-Exclusion}
    2920 
    2921 Uncontented mutual exclusion, which frequently occurs, is measured by entering/leaving a critical section.
    2922 For monitors, entering and leaving a monitor function is measured.
    2923 To put the results in context, the cost of entering a non-inline function and the cost of acquiring and releasing a @pthread_mutex@ lock is also measured.
    2924 Figure~\ref{f:mutex} shows the code for \CFA with all results in Table~\ref{tab:mutex}.
    2925 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    2926 
    2927 \begin{multicols}{2}
    2928 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    2929 \begin{cfa}
    2930 @monitor@ M {} m1/*, m2, m3, m4*/;
    2931 void __attribute__((noinline))
    2932 do_call( M & @mutex m/*, m2, m3, m4*/@ ) {}
    2933 int main() {
    2934         BENCH(
    2935                 for( N ) do_call( m1/*, m2, m3, m4*/ );
    2936         )
    2937         sout | result`ns;
    2938 }
    2939 \end{cfa}
    2940 \captionof{figure}{\CFA acquire/release mutex benchmark}
    2941 \label{f:mutex}
    2942 
    2943 \columnbreak
    2944 
    2945 \vspace*{-16pt}
    2946 \captionof{table}{Mutex comparison (nanoseconds)}
    2947 \label{tab:mutex}
    2948 \begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    2949 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    2950 test and test-and-test lock             & 19.1  & 19.0  & 0.36  \\
    2951 \CFA @mutex@ function, 1 arg.   & 46.6  & 46.8  & 0.86  \\
    2952 \CFA @mutex@ function, 2 arg.   & 84.1  & 85.3  & 1.86  \\
    2953 \CFA @mutex@ function, 4 arg.   & 158.6 & 160.7 & 3.07  \\
    2954 \uC @monitor@ member rtn.               & 54.0  & 53.7  & 0.83  \\
    2955 Java synchronized method                & 27.0  & 27.1  & 0.25  \\
    2956 Pthreads Mutex Lock                             & 33.6  & 32.7  & 1.12
     2963\CFA @signal@, 1 @monitor@      & 372.6         & 374.3         & 14.17         \\
     2964\CFA @signal@, 2 @monitor@      & 492.7         & 494.1         & 12.99         \\
     2965\CFA @signal@, 4 @monitor@      & 749.4         & 750.4         & 24.74         \\
     2966\uC @signal@                            & 320.5         & 321.0         & 3.36          \\
     2967Java @notify@                           & 10160.5       & 10169.4       & 267.71        \\
     2968Pthreads Cond. Variable         & 4949.6        & 5065.2        & 363
    29572969\end{tabular}
    29582970\end{multicols}
  • libcfa/prelude/prelude-gen.cc

    rc60a664 r99cadc60  
    1 // 
     1//
    22// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
    33//
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 // 
    7 // prelude-gen.cc -- 
    8 // 
     6//
     7// prelude-gen.cc --
     8//
    99// Author           : Rob Schluntz and Thierry Delisle
    1010// Created On       : Sat Feb 16 08:44:58 2019
     
    1212// Last Modified On : Tue Apr  2 17:18:24 2019
    1313// Update Count     : 37
    14 // 
     14//
    1515
    1616#include <algorithm>
     
    264264                for (auto cvq : qualifiersPair) {
    265265                        for (auto is_vol : { "        ", "volatile" }) {
    266                                 cout << "forall(dtype DT) void ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
     266                                cout << "forall(dtype DT) void  ?{}(" << cvq.first << type << " * " << is_vol << " &, " << cvq.second << "DT *);" << endl;
    267267                        }
    268268                }
    269                 for (auto cvq : qualifiersSingle) {
    270                         for (auto is_vol : { "        ", "volatile" }) {
    271                                 cout << "forall(dtype DT) void ?{}(" << cvq << type << " * " << is_vol << " &);" << endl;
    272                         }
    273                         for (auto is_vol : { "        ", "volatile" }) {
    274                                 cout << "forall(dtype DT) void ^?{}(" << cvq << type << " * " << is_vol << " &);" << endl;
    275                         }
     269        }
     270        for (auto cvq : qualifiersSingle) {
     271                for (auto is_vol : { "        ", "volatile" }) {
     272                        cout << "void  ?{}(" << cvq << "void" << " * " << is_vol << " &);" << endl;
     273                }
     274                for (auto is_vol : { "        ", "volatile" }) {
     275                        cout << "void ^?{}(" << cvq << "void" << " * " << is_vol << " &);" << endl;
     276                }
     277        }
     278
     279        for (auto cvq : qualifiersSingle) {
     280                for (auto is_vol : { "        ", "volatile" }) {
     281                        cout << "forall(dtype DT) void  ?{}(" << cvq << "  DT" << " * " << is_vol << " &);" << endl;
     282                }
     283                for (auto is_vol : { "        ", "volatile" }) {
     284                        cout << "forall(dtype DT) void ^?{}(" << cvq << "  DT" << " * " << is_vol << " &);" << endl;
    276285                }
    277286        }
     
    288297        cout << endl;
    289298
    290         cout << "forall(ftype FT) void  ?{}( FT *          &, zero_t ); " << endl;
     299        cout << "forall(ftype FT) void  ?{}( FT *          &, zero_t );" << endl;
    291300        cout << "forall(ftype FT) FT *                  ?=?( FT *          &, zero_t );" << endl;
    292301        cout << "forall(ftype FT) FT *                  ?=?( FT * volatile &, zero_t );" << endl;
  • libcfa/src/heap.cfa

    rc60a664 r99cadc60  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 19 16:07:46 2019
    13 // Update Count     : 548
     12// Last Modified On : Wed Jul 24 13:12:45 2019
     13// Update Count     : 550
    1414//
    1515
     
    248248
    249249#ifdef FASTLOOKUP
    250 static_assert( 16 == sizeof(HeapManager.Storage), "size of HeapManager Storage wrong" ); // FIX ME
    251 enum { LookupSizes = 65_536 + 16 };                                             // number of fast lookup sizes
     250enum { LookupSizes = 65_536 + sizeof(HeapManager.Storage) }; // number of fast lookup sizes
    252251static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    253252#endif // FASTLOOKUP
     
    869868                void * area;
    870869                if ( unlikely( alignment != 0 ) ) {                             // previous request memalign?
    871                         area = memalign( alignment, size );                     // create new area
     870                        area = memalign( alignment, size );                     // create new aligned area
    872871                } else {
    873872                        area = mallocNoStats( size );                           // create new area
  • libcfa/src/stdlib.hfa

    rc60a664 r99cadc60  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Apr 24 17:35:43 2019
    13 // Update Count     : 352
     12// Last Modified On : Tue Jul 23 14:14:59 2019
     13// Update Count     : 373
    1414//
    1515
     
    1717
    1818#include "bits/defs.hfa"
     19#include "bits/align.hfa"
    1920
    2021#include <stdlib.h>                                                                             // *alloc, strto*, ato*
     22
    2123extern "C" {
    2224        void * memalign( size_t align, size_t size );           // malloc.h
     
    3941
    4042        T * malloc( void ) {
    41                 return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     43                if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     44                else return (T *)memalign( _Alignof(T), sizeof(T) );
    4245        } // malloc
    4346
    4447        T * calloc( size_t dim ) {
    45                 return (T *)(void *)calloc( dim, sizeof(T) );   // C calloc
     48                if ( _Alignof(T) <= libAlign() )return (T *)(void *)calloc( dim, sizeof(T) ); // C calloc
     49                else return (T *)cmemalign( _Alignof(T), dim, sizeof(T) );
    4650        } // calloc
    4751
    4852        T * realloc( T * ptr, size_t size ) {
     53                if ( unlikely( ptr == 0 ) ) return malloc();
    4954                return (T *)(void *)realloc( (void *)ptr, size );
    5055        } // realloc
     
    6671
    6772        T * alloc( void ) {
    68                 return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     73                return malloc();
    6974        } // alloc
    7075
    7176        T * alloc( char fill ) {
    72                 T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) );     // C malloc
     77                T * ptr;
     78                if ( _Alignof(T) <= libAlign() ) ptr = (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     79                else ptr = (T *)memalign( _Alignof(T), sizeof(T) );
    7380                return (T *)memset( ptr, (int)fill, sizeof(T) ); // initialize with fill value
    7481        } // alloc
    7582
    7683        T * alloc( size_t dim ) {
    77                 return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
     84                if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
     85                else return (T *)memalign( _Alignof(T), dim * sizeof(T) );
    7886        } // alloc
    7987
    8088        T * alloc( size_t dim, char fill ) {
    81                 T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C calloc
    82                 return (T *)memset( ptr, (int)fill, dim * sizeof(T) ); // initialize with fill value
     89                return (T *)memset( (T *)alloc( dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value
    8390        } // alloc
    8491
    8592        T * alloc( T ptr[], size_t dim ) {
    86                 return (T *)(void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc
    87         } // alloc
    88 } // distribution
    89 
    90 
    91 forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
     93                return realloc( ptr, dim * sizeof(T) );
     94        } // alloc
     95} // distribution
    9296
    9397
     
    107111
    108112        T * align_alloc( size_t align, size_t dim, char fill ) {
    109                 T * ptr;
    110113                if ( fill == '\0' ) {
    111                         ptr = (T *)cmemalign( align, dim, sizeof(T) );
     114                        return (T *)cmemalign( align, dim, sizeof(T) );
    112115                } else {
    113                         ptr = (T *)memalign( align, dim * sizeof(T) );
    114                         return (T *)memset( ptr, (int)fill, dim * sizeof(T) );
     116                        return (T *)memset( (T *)memalign( align, dim * sizeof(T) ), (int)fill, dim * sizeof(T) );
    115117                } // if
    116                 return ptr;
    117         } // align_alloc
    118 } // distribution
     118        } // align_alloc
     119} // distribution
     120
     121forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
    119122
    120123
  • src/AST/Convert.cpp

    rc60a664 r99cadc60  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 09 15::37::05 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun 17 16:44:00 2019
    13 // Update Count     : 12
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:21:46 2019
     13// Update Count     : 13
    1414//
    1515
     
    26762676                );
    26772677        }
    2678 
    2679         virtual void visit( const AttrExpr * ) override final {
    2680                 assertf( false, "AttrExpr deprecated in new AST." );
    2681         }
    26822678};
    26832679
  • src/AST/porting.md

    rc60a664 r99cadc60  
    171171  * all existing uses assume `type` set if true and don't use `expr`
    172172
    173 `AttrExpr`
    174 * did not port due to feature deprecation (e.g. `expr@attribute`)
    175 
    176173`LogicalExpr`
    177174* un-defaulted constructor parameter determining `&&` or `||`
  • src/Common/Eval.cc

    rc60a664 r99cadc60  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May  6 22:24:16 2018
    13 // Update Count     : 40
     12// Last Modified On : Wed Jul 24 15:09:06 2019
     13// Update Count     : 64
    1414//
    1515
     
    2727        bool valid = true;
    2828
    29         void previsit( BaseSyntaxNode * ) { visit_children = false; }
    30         void postvisit( BaseSyntaxNode * ) { valid = false; }
     29        void previsit( const BaseSyntaxNode * ) { visit_children = false; }
     30        void postvisit( const BaseSyntaxNode * ) { valid = false; }
    3131
    32         void postvisit( ConstantExpr * expr ) {
     32        void postvisit( const SizeofExpr * ) {
     33        }
     34
     35        void postvisit( const ConstantExpr * expr ) {
    3336                value = expr->intValue();
    3437        }
    3538
    36         void postvisit( CastExpr * expr ) {
     39        void postvisit( const CastExpr * expr ) {
    3740                auto arg = eval(expr->arg);
    3841                valid = arg.second;
     
    4144        }
    4245
    43         void postvisit( VariableExpr * expr ) {
     46        void postvisit( const VariableExpr * const expr ) {
    4447                if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
    4548                        if ( EnumDecl * decl = inst->baseEnum ) {
     
    5255        }
    5356
    54         void postvisit( ApplicationExpr * expr ) {
    55                 DeclarationWithType * function = InitTweak::getFunction(expr);
     57        void postvisit( const ApplicationExpr * expr ) {
     58                DeclarationWithType * function = InitTweak::getFunction(const_cast<ApplicationExpr *>(expr));
    5659                if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
    5760                const std::string & fname = function->name;
     
    9497        void postvisit( const ast::ConstantExpr * expr ) {
    9598                value = expr->intValue();
     99        }
     100
     101        void postvisit( const ast::SizeofExpr * expr ) {
     102                if ( expr->expr ) value = eval(expr->expr).first;
     103                else if ( expr->type ) value = eval(expr->expr).first;
     104                else SemanticError( expr->location, ::toString( "Internal error: SizeofExpr has no expression or type value" ) );
    96105        }
    97106
     
    145154};
    146155
    147 std::pair<long long int, bool> eval(Expression * expr) {
     156std::pair<long long int, bool> eval( const Expression * expr) {
    148157        PassVisitor<EvalOld> ev;
    149158        if (expr) {
  • src/Common/PassVisitor.h

    rc60a664 r99cadc60  
    155155        virtual void visit( OffsetPackExpr * offsetPackExpr ) override final;
    156156        virtual void visit( const OffsetPackExpr * offsetPackExpr ) override final;
    157         virtual void visit( AttrExpr * attrExpr ) override final;
    158         virtual void visit( const AttrExpr * attrExpr ) override final;
    159157        virtual void visit( LogicalExpr * logicalExpr ) override final;
    160158        virtual void visit( const LogicalExpr * logicalExpr ) override final;
     
    301299        virtual Expression * mutate( OffsetofExpr * offsetofExpr ) override final;
    302300        virtual Expression * mutate( OffsetPackExpr * offsetPackExpr ) override final;
    303         virtual Expression * mutate( AttrExpr * attrExpr ) override final;
    304301        virtual Expression * mutate( LogicalExpr * logicalExpr ) override final;
    305302        virtual Expression * mutate( ConditionalExpr * conditionalExpr ) override final;
  • src/Common/PassVisitor.impl.h

    rc60a664 r99cadc60  
    23022302
    23032303//--------------------------------------------------------------------------
    2304 // AttrExpr
    2305 template< typename pass_type >
    2306 void PassVisitor< pass_type >::visit( AttrExpr * node ) {
    2307         VISIT_START( node );
    2308 
    2309         indexerScopedAccept( node->result, *this );
    2310         if ( node->get_isType() ) {
    2311                 maybeAccept_impl( node->type, *this );
    2312         } else {
    2313                 maybeAccept_impl( node->expr, *this );
    2314         }
    2315 
    2316         VISIT_END( node );
    2317 }
    2318 
    2319 template< typename pass_type >
    2320 void PassVisitor< pass_type >::visit( const AttrExpr * node ) {
    2321         VISIT_START( node );
    2322 
    2323         indexerScopedAccept( node->result, *this );
    2324         if ( node->get_isType() ) {
    2325                 maybeAccept_impl( node->type, *this );
    2326         } else {
    2327                 maybeAccept_impl( node->expr, *this );
    2328         }
    2329 
    2330         VISIT_END( node );
    2331 }
    2332 
    2333 template< typename pass_type >
    2334 Expression * PassVisitor< pass_type >::mutate( AttrExpr * node ) {
    2335         MUTATE_START( node );
    2336 
    2337         indexerScopedMutate( node->env   , *this );
    2338         indexerScopedMutate( node->result, *this );
    2339         if ( node->get_isType() ) {
    2340                 maybeMutate_impl( node->type, *this );
    2341         } else {
    2342                 maybeMutate_impl( node->expr, *this );
    2343         }
    2344 
    2345         MUTATE_END( Expression, node );
    2346 }
    2347 
    2348 //--------------------------------------------------------------------------
    23492304// LogicalExpr
    23502305template< typename pass_type >
  • src/Common/utility.h

    rc60a664 r99cadc60  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May  6 22:24:16 2018
    13 // Update Count     : 40
     12// Last Modified On : Wed Jul 24 14:28:19 2019
     13// Update Count     : 41
    1414//
    1515
     
    483483// -----------------------------------------------------------------------------
    484484/// evaluates expr as a long long int. If second is false, expr could not be evaluated
    485 std::pair<long long int, bool> eval(Expression * expr);
     485std::pair<long long int, bool> eval(const Expression * expr);
    486486
    487487namespace ast {
  • src/InitTweak/InitTweak.cc

    rc60a664 r99cadc60  
    99// Author           : Rob Schluntz
    1010// Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 19 14:34:00 2019
    13 // Update Count     : 6
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:21:48 2019
     13// Update Count     : 7
    1414//
    1515
     
    957957                void previsit( OffsetofExpr * ) {}
    958958                void previsit( OffsetPackExpr * ) {}
    959                 void previsit( AttrExpr * ) {}
    960959                void previsit( CommaExpr * ) {}
    961960                void previsit( LogicalExpr * ) {}
  • src/Parser/DeclarationNode.cc

    rc60a664 r99cadc60  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  1 16:49:17 2019
    13 // Update Count     : 1113
     12// Last Modified On : Thu Jul 25 22:17:10 2019
     13// Update Count     : 1116
    1414//
    1515
     
    4949const char * DeclarationNode::aggregateNames[] = { "struct", "union", "trait", "coroutine", "monitor", "thread", "NoAggregateNames" };
    5050const char * DeclarationNode::typeClassNames[] = { "otype", "dtype", "ftype", "NoTypeClassNames" };
    51 const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "zero_t", "one_t", "NoBuiltinTypeNames" };
     51const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" };
    5252
    5353UniqueName DeclarationNode::anonymous( "__anonymous" );
     
    418418        return newnode;
    419419} // DeclarationNode::newBuiltinType
    420 
    421 DeclarationNode * DeclarationNode::newAttr( const string * name, ExpressionNode * expr ) {
    422         DeclarationNode * newnode = new DeclarationNode;
    423         newnode->type = nullptr;
    424 //      newnode->attr.name = name;
    425         newnode->name = name;
    426         newnode->attr.expr = expr;
    427         return newnode;
    428 }
    429 
    430 DeclarationNode * DeclarationNode::newAttr( const string * name, DeclarationNode * type ) {
    431         DeclarationNode * newnode = new DeclarationNode;
    432         newnode->type = nullptr;
    433 //      newnode->attr.name = name;
    434         newnode->name = name;
    435         newnode->attr.type = type;
    436         return newnode;
    437 }
    438420
    439421DeclarationNode * DeclarationNode::newAttribute( const string * name, ExpressionNode * expr ) {
  • src/Parser/ParseNode.h

    rc60a664 r99cadc60  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 15 14:22:39 2019
    13 // Update Count     : 874
     12// Last Modified On : Thu Jul 25 22:17:10 2019
     13// Update Count     : 876
    1414//
    1515
     
    221221        enum TypeClass { Otype, Dtype, Ftype, Ttype, NoTypeClass };
    222222        static const char * typeClassNames[];
    223         enum BuiltinType { Valist, Zero, One, NoBuiltinType };
     223        enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };
    224224        static const char * builtinTypeNames[];
    225225
     
    252252        static DeclarationNode * newTuple( DeclarationNode * members );
    253253        static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );
    254         static DeclarationNode * newAttr( const std::string *, ExpressionNode * expr ); // @ attributes
    255         static DeclarationNode * newAttr( const std::string *, DeclarationNode * type ); // @ attributes
    256254        static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    257255        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
  • src/Parser/lex.ll

    rc60a664 r99cadc60  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Wed May 15 21:25:27 2019
    13  * Update Count     : 708
     12 * Last Modified On : Thu Jul 25 22:08:32 2019
     13 * Update Count     : 716
    1414 */
    1515
     
    5959#define QKEYWORD_RETURN(x)      RETURN_VAL(x);                          // quasi-keyword
    6060#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    61 #define ATTRIBUTE_RETURN()      RETURN_VAL( ATTR_IDENTIFIER )
    6261
    6362#ifdef HAVE_KEYWORDS_FLOATXX                                                            // GCC >= 7 => keyword, otherwise typedef
     
    9291                                // identifier, GCC: $ in identifier
    9392identifier ([a-zA-Z_$]|{universal_char})([0-9a-zA-Z_$]|{universal_char})*
    94 
    95                                 // attribute identifier, GCC: $ in identifier
    96 attr_identifier "@"{identifier}
    9793
    9894                                // numeric constants, CFA: '_' in constant
     
    218214__attribute__   { KEYWORD_RETURN(ATTRIBUTE); }                  // GCC
    219215auto                    { KEYWORD_RETURN(AUTO); }
     216__auto_type             { KEYWORD_RETURN(AUTO_TYPE); }
    220217basetypeof              { KEYWORD_RETURN(BASETYPEOF); }                 // CFA
    221218_Bool                   { KEYWORD_RETURN(BOOL); }                               // C99
     
    292289__restrict__    { KEYWORD_RETURN(RESTRICT); }                   // GCC
    293290return                  { KEYWORD_RETURN(RETURN); }
     291        /* resume                       { KEYWORD_RETURN(RESUME); }                             // CFA */
    294292short                   { KEYWORD_RETURN(SHORT); }
    295293signed                  { KEYWORD_RETURN(SIGNED); }
     
    300298_Static_assert  { KEYWORD_RETURN(STATICASSERT); }               // C11
    301299struct                  { KEYWORD_RETURN(STRUCT); }
     300        /* suspend                      { KEYWORD_RETURN(SUSPEND); }                    // CFA */
    302301switch                  { KEYWORD_RETURN(SWITCH); }
    303302thread                  { KEYWORD_RETURN(THREAD); }                             // C11
     
    333332        IDENTIFIER_RETURN();
    334333}
    335 {attr_identifier} { ATTRIBUTE_RETURN(); }
    336334
    337335                                /* numeric constants */
  • src/Parser/parser.yy

    rc60a664 r99cadc60  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 14 07:54:30 2019
    13 // Update Count     : 4355
     12// Last Modified On : Thu Jul 25 22:31:38 2019
     13// Update Count     : 4359
    1414//
    1515
     
    272272%token ZERO_T ONE_T                                                                             // CFA
    273273%token VALIST                                                                                   // GCC
     274%token AUTO_TYPE                                                                                // GCC
    274275%token TYPEOF BASETYPEOF LABEL                                                  // GCC
    275276%token ENUM STRUCT UNION
     
    288289%token<tok> IDENTIFIER                  QUOTED_IDENTIFIER               TYPEDEFname                             TYPEGENname
    289290%token<tok> TIMEOUT                             WOR
    290 %token<tok> ATTR_IDENTIFIER             ATTR_TYPEDEFname                ATTR_TYPEGENname
    291291%token<tok> INTEGERconstant             CHARACTERconstant               STRINGliteral
    292292%token<tok> DIRECTIVE
     
    312312%token ATassign                                                                                 // @=
    313313
    314 %type<tok> identifier  no_attr_identifier
    315 %type<tok> identifier_or_type_name  no_attr_identifier_or_type_name  attr_name
     314%type<tok> identifier
     315%type<tok> identifier_or_type_name  attr_name
    316316%type<tok> quasi_keyword
    317317%type<constant> string_literal
     
    546546        ;
    547547
    548 no_attr_identifier:
     548identifier:
    549549        IDENTIFIER
    550550        | quasi_keyword
    551551        | '@'                                                                                           // CFA
    552552                { Token tok = { new string( DeclarationNode::anonymous.newName() ), yylval.tok.loc }; $$ = tok; }
    553         ;
    554 
    555 identifier:
    556         no_attr_identifier
    557         | ATTR_IDENTIFIER                                                                       // CFA
    558553        ;
    559554
     
    594589        | '(' comma_expression ')' '`' IDENTIFIER                       // CFA, postfix call
    595590                { $$ = new ExpressionNode( build_func( new ExpressionNode( build_postfix_name( $5 ) ), $2 ) ); }
    596         | type_name '.' no_attr_identifier                                      // CFA, nested type
     591        | type_name '.' identifier                                                      // CFA, nested type
    597592                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
    598593        | type_name '.' '[' field_name_list ']'                         // CFA, nested type / tuple field selector
     
    647642        | postfix_expression '(' argument_expression_list ')'
    648643                { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
    649         | postfix_expression '.' no_attr_identifier
     644        | postfix_expression '.' identifier
    650645                { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
    651646        | postfix_expression '.' INTEGERconstant                        // CFA, tuple index
     
    655650        | postfix_expression '.' '[' field_name_list ']'        // CFA, tuple field selector
    656651                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
    657         | postfix_expression ARROW no_attr_identifier
     652        | postfix_expression ARROW identifier
    658653                { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
    659654        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
     
    718713        | FLOATINGconstant fraction_constants_opt
    719714                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
    720         | no_attr_identifier fraction_constants_opt
     715        | identifier fraction_constants_opt
    721716                {
    722717                        $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     
    776771        | ALIGNOF '(' type_no_function ')'                                      // GCC, type alignment
    777772                { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); }
    778         | OFFSETOF '(' type_no_function ',' no_attr_identifier ')'
     773        | OFFSETOF '(' type_no_function ',' identifier ')'
    779774                { $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) ); }
    780         | ATTR_IDENTIFIER
    781                 { $$ = new ExpressionNode( new AttrExpr( build_varref( $1 ), maybeMoveBuild< Expression >( (ExpressionNode *)nullptr ) ) ); }
    782         | ATTR_IDENTIFIER '(' argument_expression ')'
    783                 { $$ = new ExpressionNode( new AttrExpr( build_varref( $1 ), maybeMoveBuild< Expression >( $3 ) ) ); }
    784         | ATTR_IDENTIFIER '(' type ')'
    785                 { $$ = new ExpressionNode( new AttrExpr( build_varref( $1 ), maybeMoveBuildType( $3 ) ) ); }
    786775        ;
    787776
     
    10181007
    10191008labeled_statement:
    1020                 // labels cannot be identifiers 0 or 1 or ATTR_IDENTIFIER
     1009                // labels cannot be identifiers 0 or 1
    10211010        identifier_or_type_name ':' attribute_list_opt statement
    10221011                { $$ = $4->add_label( $1, $3 ); }
     
    13861375        | type_specifier_nobody variable_abstract_declarator
    13871376                { $$ = $2->addType( $1 ); }
    1388         | cfa_abstract_declarator_tuple no_attr_identifier      // CFA
     1377        | cfa_abstract_declarator_tuple identifier                      // CFA
    13891378                { $$ = $1->addName( $2 ); }
    13901379        | cfa_abstract_declarator_tuple                                         // CFA
     
    14501439
    14511440label_list:
    1452         no_attr_identifier
     1441        identifier
    14531442                {
    14541443                        $$ = new LabelNode(); $$->labels.push_back( *$1 );
    14551444                        delete $1;                                                                      // allocated by lexer
    14561445                }
    1457         | label_list ',' no_attr_identifier
     1446        | label_list ',' identifier
    14581447                {
    14591448                        $$ = $1; $1->labels.push_back( *$3 );
     
    15001489
    15011490local_label_list:                                                                               // GCC, local label
    1502         no_attr_identifier_or_type_name
    1503         | local_label_list ',' no_attr_identifier_or_type_name
     1491        identifier_or_type_name
     1492        | local_label_list ',' identifier_or_type_name
    15041493        ;
    15051494
     
    16231612                        $$ = $2->addTypedef();
    16241613                }
    1625         | cfa_typedef_declaration pop ',' push no_attr_identifier
     1614        | cfa_typedef_declaration pop ',' push identifier
    16261615                {
    16271616                        typedefTable.addToEnclosingScope( *$5, TYPEDEFname, "3" );
     
    16631652typedef_expression:
    16641653                // GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
    1665         TYPEDEF no_attr_identifier '=' assignment_expression
     1654        TYPEDEF identifier '=' assignment_expression
    16661655                {
    16671656                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
    16681657                        SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
    16691658                }
    1670         | typedef_expression pop ',' push no_attr_identifier '=' assignment_expression
     1659        | typedef_expression pop ',' push identifier '=' assignment_expression
    16711660                {
    16721661                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
     
    18711860        | VALIST                                                                                        // GCC, __builtin_va_list
    18721861                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Valist ); }
     1862        | AUTO_TYPE
     1863                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::AutoType ); }
    18731864        ;
    18741865
     
    19121903        | BASETYPEOF '(' comma_expression ')'                           // CFA: basetypeof( a+b ) y;
    19131904                { $$ = DeclarationNode::newTypeof( $3, true ); }
    1914         | ATTR_TYPEGENname '(' type ')'                                         // CFA: e.g., @type( x ) y;
    1915                 { $$ = DeclarationNode::newAttr( $1, $3 ); }
    1916         | ATTR_TYPEGENname '(' comma_expression ')'                     // CFA: e.g., @type( a+b ) y;
    1917                 { $$ = DeclarationNode::newAttr( $1, $3 ); }
    19181905        | ZERO_T                                                                                        // CFA
    19191906                { $$ = DeclarationNode::newBuiltinType( DeclarationNode::Zero ); }
     
    20242011          '{' field_declaration_list_opt '}' type_parameters_opt
    20252012                { $$ = DeclarationNode::newAggregate( $1, nullptr, $7, $5, true )->addQualifiers( $2 ); }
    2026         | aggregate_key attribute_list_opt no_attr_identifier fred
     2013        | aggregate_key attribute_list_opt identifier fred
    20272014                {
    20282015                        typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname ); // create typedef
     
    20502037
    20512038aggregate_type_nobody:                                                                  // struct, union - {...}
    2052         aggregate_key attribute_list_opt no_attr_identifier fred
     2039        aggregate_key attribute_list_opt identifier fred
    20532040                {
    20542041                        typedefTable.makeTypedef( *$3, forall || typedefTable.getEnclForall() ? TYPEGENname : TYPEDEFname );
     
    21512138cfa_field_declaring_list:                                                               // CFA, new style field declaration
    21522139        // bit-fields are handled by C declarations
    2153         cfa_abstract_declarator_tuple no_attr_identifier_or_type_name
     2140        cfa_abstract_declarator_tuple identifier_or_type_name
    21542141                { $$ = $1->addName( $2 ); }
    2155         | cfa_field_declaring_list ',' no_attr_identifier_or_type_name
     2142        | cfa_field_declaring_list ',' identifier_or_type_name
    21562143                { $$ = $1->appendList( $1->cloneType( $3 ) ); }
    21572144        ;
     
    21782165        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    21792166                { $$ = DeclarationNode::newEnum( nullptr, $4, true )->addQualifiers( $2 ); }
    2180         | ENUM attribute_list_opt no_attr_identifier
     2167        | ENUM attribute_list_opt identifier
    21812168                { typedefTable.makeTypedef( *$3 ); }
    21822169          '{' enumerator_list comma_opt '}'
     
    21892176
    21902177enum_type_nobody:                                                                               // enum - {...}
    2191         ENUM attribute_list_opt no_attr_identifier
     2178        ENUM attribute_list_opt identifier
    21922179                {
    21932180                        typedefTable.makeTypedef( *$3 );
     
    22022189
    22032190enumerator_list:
    2204         no_attr_identifier_or_type_name enumerator_value_opt
     2191        identifier_or_type_name enumerator_value_opt
    22052192                { $$ = DeclarationNode::newEnumConstant( $1, $2 ); }
    2206         | enumerator_list ',' no_attr_identifier_or_type_name enumerator_value_opt
     2193        | enumerator_list ',' identifier_or_type_name enumerator_value_opt
    22072194                { $$ = $1->appendList( DeclarationNode::newEnumConstant( $3, $4 ) ); }
    22082195        ;
     
    23122299
    23132300identifier_list:                                                                                // K&R-style parameter list => no types
    2314         no_attr_identifier
     2301        identifier
    23152302                { $$ = DeclarationNode::newName( $1 ); }
    2316         | identifier_list ',' no_attr_identifier
     2303        | identifier_list ',' identifier
    23172304                { $$ = $1->appendList( DeclarationNode::newName( $3 ) ); }
    23182305        ;
     
    23202307identifier_or_type_name:
    23212308        identifier
    2322         | TYPEDEFname
    2323         | TYPEGENname
    2324         ;
    2325 
    2326 no_attr_identifier_or_type_name:
    2327         no_attr_identifier
    23282309        | TYPEDEFname
    23292310        | TYPEGENname
     
    23802361designation:
    23812362        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    2382         | no_attr_identifier ':'                                                        // GCC, field name
     2363        | identifier ':'                                                                        // GCC, field name
    23832364                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    23842365        ;
     
    23922373
    23932374designator:
    2394         '.' no_attr_identifier                                                          // C99, field name
     2375        '.' identifier                                                                          // C99, field name
    23952376                { $$ = new ExpressionNode( build_varref( $2 ) ); }
    23962377        | '[' push assignment_expression pop ']'                        // C99, single array element
     
    24372418
    24382419type_parameter:                                                                                 // CFA
    2439         type_class no_attr_identifier_or_type_name
     2420        type_class identifier_or_type_name
    24402421                { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
    24412422          type_initializer_opt assertion_list_opt
     
    24702451
    24712452assertion:                                                                                              // CFA
    2472         '|' no_attr_identifier_or_type_name '(' type_list ')'
     2453        '|' identifier_or_type_name '(' type_list ')'
    24732454                { $$ = DeclarationNode::newTraitUse( $2, $4 ); }
    24742455        | '|' '{' push trait_declaration_list pop '}'
     
    25072488
    25082489type_declarator_name:                                                                   // CFA
    2509         no_attr_identifier_or_type_name
     2490        identifier_or_type_name
    25102491                {
    25112492                        typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
    25122493                        $$ = DeclarationNode::newTypeDecl( $1, 0 );
    25132494                }
    2514         | no_attr_identifier_or_type_name '(' type_parameter_list ')'
     2495        | identifier_or_type_name '(' type_parameter_list ')'
    25152496                {
    25162497                        typedefTable.addToEnclosingScope( *$1, TYPEGENname, "11" );
     
    25202501
    25212502trait_specifier:                                                                                // CFA
    2522         TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' '}'
     2503        TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    25232504                { $$ = DeclarationNode::newTrait( $2, $4, 0 ); }
    2524         | TRAIT no_attr_identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
     2505        | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    25252506                { $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
    25262507        ;
  • src/ResolvExpr/AlternativeFinder.cc

    rc60a664 r99cadc60  
    1010// Created On       : Sat May 16 23:52:08 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Nov  1 21:00:56 2018
    13 // Update Count     : 35
     12// Last Modified On : Thu Jul 25 22:37:46 2019
     13// Update Count     : 37
    1414//
    1515
     
    7979                void postvisit( OffsetofExpr * offsetofExpr );
    8080                void postvisit( OffsetPackExpr * offsetPackExpr );
    81                 void postvisit( AttrExpr * attrExpr );
    8281                void postvisit( LogicalExpr * logicalExpr );
    8382                void postvisit( ConditionalExpr * conditionalExpr );
     
    14041403        }
    14051404
    1406         namespace {
    1407                 void resolveAttr( SymTab::Indexer::IdData data, const FunctionType * function, Type * argType, const TypeEnvironment &env, AlternativeFinder & finder ) {
    1408                         // assume no polymorphism
    1409                         // assume no implicit conversions
    1410                         assert( function->parameters.size() == 1 );
    1411                         PRINT(
    1412                                 std::cerr << "resolvAttr: funcDecl is ";
    1413                                 data.id->print( std::cerr );
    1414                                 std::cerr << " argType is ";
    1415                                 argType->print( std::cerr );
    1416                                 std::cerr << std::endl;
    1417                         )
    1418                         const SymTab::Indexer & indexer = finder.get_indexer();
    1419                         AltList & alternatives = finder.get_alternatives();
    1420                         if ( typesCompatibleIgnoreQualifiers( argType, function->parameters.front()->get_type(), indexer, env ) ) {
    1421                                 Cost cost = Cost::zero;
    1422                                 Expression * newExpr = data.combine( cost );
    1423                                 alternatives.push_back( Alternative{
    1424                                         new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{},
    1425                                         AssertionList{}, Cost::zero, cost } );
    1426                                 for ( DeclarationWithType * retVal : function->returnVals ) {
    1427                                         alternatives.back().expr->result = retVal->get_type()->clone();
    1428                                 } // for
    1429                         } // if
    1430                 }
    1431         }
    1432 
    1433         void AlternativeFinder::Finder::postvisit( AttrExpr * attrExpr ) {
    1434                 // assume no 'pointer-to-attribute'
    1435                 NameExpr * nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
    1436                 assert( nameExpr );
    1437                 std::list< SymTab::Indexer::IdData > attrList;
    1438                 indexer.lookupId( nameExpr->get_name(), attrList );
    1439                 if ( attrExpr->get_isType() || attrExpr->get_expr() ) {
    1440                         for ( auto & data : attrList ) {
    1441                                 const DeclarationWithType * id = data.id;
    1442                                 // check if the type is function
    1443                                 if ( const FunctionType * function = dynamic_cast< const FunctionType * >( id->get_type() ) ) {
    1444                                         // assume exactly one parameter
    1445                                         if ( function->parameters.size() == 1 ) {
    1446                                                 if ( attrExpr->get_isType() ) {
    1447                                                         resolveAttr( data, function, attrExpr->get_type(), env, altFinder);
    1448                                                 } else {
    1449                                                         AlternativeFinder finder( indexer, env );
    1450                                                         finder.find( attrExpr->get_expr() );
    1451                                                         for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    1452                                                                 if ( choice->expr->get_result()->size() == 1 ) {
    1453                                                                         resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder );
    1454                                                                 } // fi
    1455                                                         } // for
    1456                                                 } // if
    1457                                         } // if
    1458                                 } // if
    1459                         } // for
    1460                 } else {
    1461                         for ( auto & data : attrList ) {
    1462                                 Cost cost = Cost::zero;
    1463                                 Expression * newExpr = data.combine( cost );
    1464                                 alternatives.push_back( Alternative{
    1465                                         newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } );
    1466                                 renameTypes( alternatives.back().expr );
    1467                         } // for
    1468                 } // if
    1469         }
    1470 
    14711405        void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) {
    14721406                AlternativeFinder firstFinder( indexer, env );
  • src/SymTab/Demangle.cc

    rc60a664 r99cadc60  
    99// Author           : Rob Schluntz
    1010// Created On       : Thu Jul 19 12:52:41 2018
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Thu Jul 19 12:54:35 2018
    13 // Update Count     : 2
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Jul 30 13:46:33 2019
     13// Update Count     : 3
    1414//
    1515
     
    313313                        typeString = "_Atomic " + typeString;
    314314                } // if
    315                 if ( type->get_lvalue() ) {
    316                         // when not generating C code, print lvalue for debugging.
    317                         typeString = "lvalue " + typeString;
    318                 }
    319315        }
    320316}
  • src/SymTab/Mangler.cc

    rc60a664 r99cadc60  
    1010// Created On       : Sun May 17 21:40:29 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 15:49:26 2017
    13 // Update Count     : 23
     12// Last Modified On : Tue Jul 30 13:46:10 2019
     13// Update Count     : 26
    1414//
    1515#include "Mangler.h"
     
    377377                                        mangleName << Encoding::qualifiers.at(Type::Mutex);
    378378                                } // if
    379                                 if ( type->get_lvalue() ) {
    380                                         // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
    381                                         mangleName << Encoding::qualifiers.at(Type::Lvalue);
    382                                 }
    383 
    384379                                if ( inFunctionType ) {
    385380                                        // turn off inFunctionType so that types can be differentiated for nested qualifiers
     
    724719                                mangleName << Encoding::qualifiers.at(Type::Mutex);
    725720                        } // if
    726                         if ( type->is_lvalue() ) {
    727                                 // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
    728                                 mangleName << Encoding::qualifiers.at(Type::Lvalue);
    729                         }
    730 
    731721                        if ( inFunctionType ) {
    732722                                // turn off inFunctionType so that types can be differentiated for nested qualifiers
  • src/SynTree/Expression.cc

    rc60a664 r99cadc60  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb 19 18:10:55 2019
    13 // Update Count     : 60
     12// Last Modified On : Thu Jul 25 22:21:48 2019
     13// Update Count     : 61
    1414//
    1515
     
    249249        os << "Offset pack expression on ";
    250250        type->print(os, indent+1);
    251         Expression::print( os, indent );
    252 }
    253 
    254 AttrExpr::AttrExpr( Expression * attr, Expression * expr_ ) :
    255                 Expression(), attr( attr ), expr(expr_), type(0), isType(false) {
    256 }
    257 
    258 AttrExpr::AttrExpr( Expression * attr, Type * type_ ) :
    259                 Expression(), attr( attr ), expr(0), type(type_), isType(true) {
    260 }
    261 
    262 AttrExpr::AttrExpr( const AttrExpr & other ) :
    263                 Expression( other ), attr( maybeClone( other.attr ) ), expr( maybeClone( other.expr ) ), type( maybeClone( other.type ) ), isType( other.isType ) {
    264 }
    265 
    266 AttrExpr::~AttrExpr() {
    267         delete attr;
    268         delete expr;
    269         delete type;
    270 }
    271 
    272 void AttrExpr::print( std::ostream & os, Indenter indent) const {
    273         os << "Attr ";
    274         attr->print( os, indent+1);
    275         if ( isType || expr ) {
    276                 os << "applied to: ";
    277                 if (isType) type->print(os, indent+1);
    278                 else expr->print(os, indent+1);
    279         } // if
    280251        Expression::print( os, indent );
    281252}
  • src/SynTree/Expression.h

    rc60a664 r99cadc60  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Feb 18 18:29:51 2019
    13 // Update Count     : 49
     12// Last Modified On : Thu Jul 25 22:21:44 2019
     13// Update Count     : 50
    1414//
    1515
     
    463463};
    464464
    465 /// AttrExpr represents an @attribute expression (like sizeof, but user-defined)
    466 class AttrExpr : public Expression {
    467   public:
    468         Expression * attr;
    469         Expression * expr;
    470         Type * type;
    471         bool isType;
    472 
    473         AttrExpr(Expression * attr, Expression * expr );
    474         AttrExpr( const AttrExpr & other );
    475         AttrExpr( Expression * attr, Type * type );
    476         virtual ~AttrExpr();
    477 
    478         Expression * get_attr() const { return attr; }
    479         void set_attr( Expression * newValue ) { attr = newValue; }
    480         Expression * get_expr() const { return expr; }
    481         void set_expr( Expression * newValue ) { expr = newValue; }
    482         Type * get_type() const { return type; }
    483         void set_type( Type * newValue ) { type = newValue; }
    484         bool get_isType() const { return isType; }
    485         void set_isType( bool newValue ) { isType = newValue; }
    486 
    487         virtual AttrExpr * clone() const override { return new AttrExpr( * this ); }
    488         virtual void accept( Visitor & v ) override { v.visit( this ); }
    489         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    490         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    491         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    492 };
    493 
    494465/// LogicalExpr represents a short-circuit boolean expression (&& or ||)
    495466class LogicalExpr : public Expression {
  • src/SynTree/Mutator.h

    rc60a664 r99cadc60  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jul 24 16:31:00 2017
    13 // Update Count     : 16
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:37:46 2019
     13// Update Count     : 17
    1414//
    1515#pragma once
     
    7474        virtual Expression * mutate( OffsetofExpr * offsetofExpr ) = 0;
    7575        virtual Expression * mutate( OffsetPackExpr * offsetPackExpr ) = 0;
    76         virtual Expression * mutate( AttrExpr * attrExpr ) = 0;
    7776        virtual Expression * mutate( LogicalExpr * logicalExpr ) = 0;
    7877        virtual Expression * mutate( ConditionalExpr * conditionalExpr ) = 0;
  • src/SynTree/SynTree.h

    rc60a664 r99cadc60  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jul 24 16:54:00 2017
    13 // Update Count     : 11
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:37:45 2019
     13// Update Count     : 12
    1414//
    1515
     
    7979class OffsetofExpr;
    8080class OffsetPackExpr;
    81 class AttrExpr;
    8281class LogicalExpr;
    8382class ConditionalExpr;
  • src/SynTree/Visitor.h

    rc60a664 r99cadc60  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jul 24 16:28:00 2017
    13 // Update Count     : 13
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Jul 25 22:21:49 2019
     13// Update Count     : 14
    1414//
    1515
     
    123123        virtual void visit( OffsetPackExpr * node ) { visit( const_cast<const OffsetPackExpr *>(node) ); }
    124124        virtual void visit( const OffsetPackExpr * offsetPackExpr ) = 0;
    125         virtual void visit( AttrExpr * node ) { visit( const_cast<const AttrExpr *>(node) ); }
    126         virtual void visit( const AttrExpr * attrExpr ) = 0;
    127125        virtual void visit( LogicalExpr * node ) { visit( const_cast<const LogicalExpr *>(node) ); }
    128126        virtual void visit( const LogicalExpr * logicalExpr ) = 0;
  • tests/pybin/settings.py

    rc60a664 r99cadc60  
    2222                'x86-64'                : 'x64',
    2323                'x86_64'                : 'x64',
     24                'aarch64'               : 'x64',
    2425                'x86'                   : 'x86',
    2526                'i386'          : 'x86',
     
    4041                        canonical_host = Architecture.make_canonical( config.HOSTARCH )
    4142                except KeyError:
    42                         print("Unkown host architecture %s" % config.HOSTARCH, file=sys.stderr)
     43                        print("Unknown host architecture %s" % config.HOSTARCH, file=sys.stderr)
    4344                        sys.exit(1)
    4445
     
    4748                                arch = Architecture.make_canonical( arch )
    4849                        except KeyError:
    49                                 print("Unkown architecture %s" % arch, file=sys.stderr)
     50                                print("Unknown architecture %s" % arch, file=sys.stderr)
    5051                                sys.exit(1)
    5152
Note: See TracChangeset for help on using the changeset viewer.