Changes in / [223a633:33c3ded]


Ignore:
Files:
123 added
146 deleted
157 edited

Legend:

Unmodified
Added
Removed
  • Jenkins/FullBuild

    r223a633 r33c3ded  
    1717
    1818                                parallel (
    19                                         gcc_8_x86: { trigger_build( 'gcc-8',   'x86' ) },
    20                                         gcc_7_x86: { trigger_build( 'gcc-7',   'x86' ) },
     19                                        clang_x86: { trigger_build( 'gcc-8',   'x86' ) },
     20                                        gcc_5_x86: { trigger_build( 'gcc-7',   'x86' ) },
    2121                                        gcc_6_x86: { trigger_build( 'gcc-6',   'x86' ) },
    2222                                        gcc_9_x64: { trigger_build( 'gcc-9',   'x64' ) },
  • Jenkinsfile

    r223a633 r33c3ded  
    392392                        break
    393393                        case 'clang':
    394                                 this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-9', '-flto=thin -flto-jobs=0')
     394                                this.Compiler = new CC_Desc('clang', 'clang++-6.0', 'gcc-6', '-flto=thin -flto-jobs=0')
    395395                        break
    396396                        default :
  • benchmark/Makefile.am

    r223a633 r33c3ded  
    113113creation_cfa_generator_DURATION = 1000000000
    114114creation_upp_coroutine_DURATION = ${creation_cfa_coroutine_eager_DURATION}
     115creation_cfa_thread_DURATION = 10000000
     116creation_upp_thread_DURATION = ${creation_cfa_thread_DURATION}
    115117creation_DURATION = 10000000
    116118
     
    146148
    147149cleancsv:
    148         rm -f compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv
     150        rm -f compile.csv basic.csv ctxswitch.csv mutex.csv scheduling.csv
    149151
    150152jenkins$(EXEEXT): cleancsv
     
    157159        +make mutex.csv
    158160        -+make mutex.diff.csv
    159         +make schedint.csv
    160         -+make schedint.diff.csv
     161        +make scheduling.csv
     162        -+make scheduling.diff.csv
    161163@DOifskipcompile@
    162164        cat compile.csv
     
    167169        cat mutex.csv
    168170        -cat mutex.diff.csv
    169         cat schedint.csv
    170         -cat schedint.diff.csv
     171        cat scheduling.csv
     172        -cat scheduling.diff.csv
    171173
    172174compile.csv:
     
    198200        $(srcdir)/fixcsv.sh $@
    199201
    200 schedint.csv:
     202scheduling.csv:
    201203        echo "building $@"
    202204        echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@
     
    289291ctxswitch-python_coroutine$(EXEEXT):
    290292        $(BENCH_V_PY)echo "#!/bin/sh" > a.out
    291         echo "python3 $(srcdir)/ctxswitch/python_cor.py \"$$""@\"" >> a.out
     293        echo "python3.7 $(srcdir)/ctxswitch/python_cor.py" >> a.out
    292294        chmod a+x a.out
    293295
    294296ctxswitch-nodejs_coroutine$(EXEEXT):
    295297        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    296         echo "nodejs $(srcdir)/ctxswitch/node_cor.js \"$$""@\"" >> a.out
     298        echo "nodejs $(srcdir)/ctxswitch/node_cor.js" >> a.out
    297299        chmod a+x a.out
    298300
    299301ctxswitch-nodejs_await$(EXEEXT):
    300302        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    301         echo "nodejs $(srcdir)/ctxswitch/node_await.js \"$$""@\"" >> a.out
     303        echo "nodejs $(srcdir)/ctxswitch/node_await.js" >> a.out
    302304        chmod a+x a.out
    303305
     
    311313        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/ctxswitch/JavaThread.java
    312314        echo "#!/bin/sh" > a.out
    313         echo "java JavaThread \"$$""@\"" >> a.out
     315        echo "java JavaThread" >> a.out
    314316        chmod a+x a.out
    315317
     
    353355        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/mutex/JavaThread.java
    354356        echo "#!/bin/sh" > a.out
    355         echo "java JavaThread \"$$""@\"" >> a.out
     357        echo "java JavaThread" >> a.out
    356358        chmod a+x a.out
    357359
     
    385387        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/schedint/JavaThread.java
    386388        echo "#!/bin/sh" > a.out
    387         echo "java JavaThread \"$$""@\"" >> a.out
     389        echo "java JavaThread" >> a.out
    388390        chmod a+x a.out
    389391
     
    452454creation-python_coroutine$(EXEEXT):
    453455        $(BENCH_V_PY)echo "#!/bin/sh" > a.out
    454         echo "python3 $(srcdir)/creation/python_cor.py \"$$""@\"" >> a.out
     456        echo "python3.7 $(srcdir)/creation/python_cor.py" >> a.out
    455457        chmod a+x a.out
    456458
    457459creation-nodejs_coroutine$(EXEEXT):
    458460        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    459         echo "nodejs $(srcdir)/creation/node_cor.js \"$$""@\"" >> a.out
     461        echo "nodejs $(srcdir)/creation/node_cor.js" >> a.out
    460462        chmod a+x a.out
    461463
     
    469471        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/creation/JavaThread.java
    470472        echo "#!/bin/sh" > a.out
    471         echo "java JavaThread \"$$""@\"" >> a.out
     473        echo "java JavaThread" >> a.out
    472474        chmod a+x a.out
    473475
     
    490492
    491493compile-array$(EXEEXT):
    492         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/array.cfa
     494        $(CFACOMPILE) -fsyntax-only -w $(testdir)/array.cfa
    493495
    494496compile-attributes$(EXEEXT):
    495         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/attributes.cfa
     497        $(CFACOMPILE) -fsyntax-only -w $(testdir)/attributes.cfa
    496498
    497499compile-empty$(EXEEXT):
    498         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(srcdir)/compile/empty.cfa
     500        $(CFACOMPILE) -fsyntax-only -w $(srcdir)/compile/empty.cfa
    499501
    500502compile-expression$(EXEEXT):
    501         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/expression.cfa
     503        $(CFACOMPILE) -fsyntax-only -w $(testdir)/expression.cfa
    502504
    503505compile-io$(EXEEXT):
    504         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/io1.cfa
     506        $(CFACOMPILE) -fsyntax-only -w $(testdir)/io1.cfa
    505507
    506508compile-monitor$(EXEEXT):
    507         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/monitor.cfa
     509        $(CFACOMPILE) -fsyntax-only -w $(testdir)/concurrent/monitor.cfa
    508510
    509511compile-operators$(EXEEXT):
    510         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/operators.cfa
     512        $(CFACOMPILE) -fsyntax-only -w $(testdir)/operators.cfa
    511513
    512514compile-thread$(EXEEXT):
    513         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/thread.cfa
     515        $(CFACOMPILE) -fsyntax-only -w $(testdir)/concurrent/thread.cfa
    514516
    515517compile-typeof$(EXEEXT):
    516         $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/typeof.cfa
     518        $(CFACOMPILE) -fsyntax-only -w $(testdir)/typeof.cfa
    517519
    518520## =========================================================================================================
  • benchmark/creation/JavaThread.java

    r223a633 r33c3ded  
    4747        }
    4848        public static void main(String[] args) throws InterruptedException {
    49                 if ( args.length > 1 ) System.exit( 1 );
    50                 if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
     49                if ( args.length > 2 ) System.exit( 1 );
     50                if ( args.length == 2 ) { times = Long.parseLong(args[1]); }
    5151
    5252                for (int i = Integer.parseInt("5"); --i >= 0 ; ) {
  • benchmark/ctxswitch/JavaThread.java

    r223a633 r33c3ded  
    4040        }
    4141        public static void main(String[] args) throws InterruptedException {
    42                 if ( args.length > 1 ) System.exit( 1 );
    43                 if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
     42                if ( args.length > 2 ) System.exit( 1 );
     43                if ( args.length == 2 ) { times = Long.parseLong(args[1]); }
    4444
    4545                for (int i = Integer.parseInt("5"); --i >= 0 ; ) {
  • benchmark/io/http/main.cfa

    r223a633 r33c3ded  
    125125                                                workers[i].flags   = 0;
    126126                                        }
    127                                         unpark( workers[i] );
     127                                        unpark( workers[i] __cfaabi_dbg_ctx2 );
    128128                                }
    129129                                printf("%d workers started on %d processors\n", options.clopts.nworkers, options.clopts.nprocs);
  • benchmark/io/http/worker.cfa

    r223a633 r33c3ded  
    2222
    2323void main( Worker & this ) {
    24         park();
     24        park( __cfaabi_dbg_ctx );
    2525        /* paranoid */ assert( this.pipe[0] != -1 );
    2626        /* paranoid */ assert( this.pipe[1] != -1 );
  • benchmark/io/readv.cfa

    r223a633 r33c3ded  
    5454
    5555void main( Reader & ) {
    56         park();
     56        park( __cfaabi_dbg_ctx );
    5757        /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) );
    5858
     
    151151
    152152                                for(i; nthreads) {
    153                                         unpark( threads[i] );
     153                                        unpark( threads[i] __cfaabi_dbg_ctx2 );
    154154                                }
    155155                                wait(duration, start, end, is_tty);
  • benchmark/mutex/JavaThread.java

    r223a633 r33c3ded  
    4747        }
    4848        public static void main(String[] args) throws InterruptedException {
    49                 if ( args.length > 1 ) System.exit( 1 );
    50                 if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
     49                if ( args.length > 2 ) System.exit( 1 );
     50                if ( args.length == 2 ) { times = Long.parseLong(args[1]); }
    5151
    5252                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
  • benchmark/readyQ/yield.cfa

    r223a633 r33c3ded  
    3232
    3333void main( Yielder & this ) {
    34         park();
     34        park( __cfaabi_dbg_ctx );
    3535        /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) );
    3636
     
    7070
    7171                                for(i; nthreads) {
    72                                         unpark( threads[i] );
     72                                        unpark( threads[i] __cfaabi_dbg_ctx2 );
    7373                                }
    7474                                wait(duration, start, end, is_tty);
  • benchmark/schedint/JavaThread.java

    r223a633 r33c3ded  
    7575        }
    7676        public static void main(String[] args) throws InterruptedException {
    77                 if ( args.length > 1 ) System.exit( 1 );
    78                 if ( args.length == 1 ) { times = Long.parseLong(args[0]); }
     77                if ( args.length > 2 ) System.exit( 1 );
     78                if ( args.length == 2 ) { times = Long.parseLong(args[1]); }
    7979
    8080                for (int n = Integer.parseInt("5"); --n >= 0 ; ) {
  • doc/LaTeXmacros/common.tex

    r223a633 r33c3ded  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Mon Oct  5 09:34:46 2020
    14 %% Update Count     : 464
     13%% Last Modified On : Fri Sep  4 13:56:52 2020
     14%% Update Count     : 383
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5555\newlength{\parindentlnth}
    5656\setlength{\parindentlnth}{\parindent}
     57
     58\newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
     59\newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
     60\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
     61
     62\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
     63\newlength{\columnposn}
     64\setlength{\gcolumnposn}{2.5in}
     65\setlength{\columnposn}{\gcolumnposn}
     66\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
     67\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
     68
     69% allow escape sequence in lstinline
     70%\usepackage{etoolbox}
     71%\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}
    5772
    5873\usepackage{pslatex}                                    % reduce size of san serif font
     
    229244\usepackage{listings}                                                                   % format program code
    230245\usepackage{lstlang}
    231 \makeatletter
    232 
    233 \newcommand{\LstBasicStyle}[1]{{\lst@basicstyle{#1}}}
    234 \newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
    235 \newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
    236 
    237 \newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    238 \newlength{\columnposn}
    239 \setlength{\gcolumnposn}{2.75in}
    240 \setlength{\columnposn}{\gcolumnposn}
    241 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
    242 \newcommand{\CRT}{\global\columnposn=\gcolumnposn}
    243 
    244 % allow escape sequence in lstinline
    245 %\usepackage{etoolbox}
    246 %\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}
    247 
    248 % allow adding to lst literate
    249 \def\addToLiterate#1{\protect\edef\lst@literate{\unexpanded\expandafter{\lst@literate}\unexpanded{#1}}}
    250 \lst@Key{add to literate}{}{\addToLiterate{#1}}
    251 \makeatother
    252 
    253 \newcommand{\CFAStyle}{%
     246
     247\newcommand{\CFADefaults}{%
    254248\lstset{
     249language=CFA,
    255250columns=fullflexible,
    256251basicstyle=\linespread{0.9}\sf,                 % reduce line spacing and use sanserif font
     
    267262belowskip=3pt,
    268263% replace/adjust listing characters that look bad in sanserif
    269 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     264literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    270265        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    271266        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
    272 }% lstset
    273 }% CFAStyle
    274 
    275 \ifdefined\CFALatin% extra Latin-1 escape characters
    276 \lstnewenvironment{cfa}[1][]{
    277 \lstset{
    278 language=CFA,
    279 moredelim=**[is][\color{red}]{®}{®},    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     267moredelim=**[is][\color{red}]{?}{?},    % red highlighting ?...? (registered trademark symbol) emacs: C-q M-.
    280268moredelim=**[is][\color{blue}]{ß}{ß},   % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    281269moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    282270moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    283 % replace/adjust listing characters that look bad in sanserif
    284 add to literate={`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    285271}% lstset
    286 \lstset{#1}
    287 }{}
     272}% CFADefaults
     273\newcommand{\CFAStyle}{%
     274\CFADefaults
    288275% inline code ©...© (copyright symbol) emacs: C-q M-)
    289276\lstMakeShortInline©                                    % single-character for \lstinline
    290 \else% regular ASCI characters
    291 \lstnewenvironment{cfa}[1][]{
    292 \lstset{
    293 language=CFA,
    294 escapechar=\$,                                                  % LaTeX escape in CFA code
    295 moredelim=**[is][\color{red}]{@}{@},    % red highlighting @...@
    296 }% lstset
    297 \lstset{#1}
    298 }{}
    299 % inline code @...@ (at symbol)
    300 \lstMakeShortInline@                                    % single-character for \lstinline
    301 \fi%
     277}% CFAStyle
     278
     279\lstnewenvironment{cfa}[1][]
     280{\CFADefaults\lstset{#1}}
     281{}
    302282
    303283% Local Variables: %
  • doc/LaTeXmacros/lstlang.sty

    r223a633 r33c3ded  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Wed Sep 23 22:40:04 2020
    11 %% Update Count     : 24
     10%% Last Modified On : Tue Jan  8 14:40:33 2019
     11%% Update Count     : 21
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    115115                auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__,
    116116                coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally,
    117                 __float80, float80, __float128, float128, forall, ftype, generator, _Generic, _Imaginary, __imag, __imag__,
     117                __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__,
    118118                inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or,
    119                 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, thread,
     119                otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread,
    120120                _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__,
    121121                virtual, __volatile, __volatile__, waitfor, when, with, zero_t,
     
    125125
    126126% C++ programming language
    127 \lstdefinelanguage{C++}[ANSI]{C++}{
    128         morekeywords={nullptr,}
    129 }
     127\lstdefinelanguage{C++}[ANSI]{C++}{}
    130128
    131129% uC++ programming language, based on ANSI C++
  • doc/bibliography/pl.bib

    r223a633 r33c3ded  
    10051005    key         = {Cforall Benchmarks},
    10061006    author      = {{\textsf{C}{$\mathbf{\forall}$} Benchmarks}},
    1007     howpublished= {\href{https://github.com/cforall/ConcurrentBenchmarks_SPE20}{https://\-github.com/\-cforall/\-ConcurrentBenchmarks\_SPE20}},
     1007    howpublished= {\href{https://plg.uwaterloo.ca/~cforall/doc/CforallConcurrentBenchmarks.tar}{https://\-plg.uwaterloo.ca/\-$\sim$cforall/\-doc/\-CforallConcurrentBenchmarks.tar}},
    10081008}
    10091009
     
    19731973    title       = {Cooperating Sequential Processes},
    19741974    institution = {Technological University},
    1975     address     = {Eindhoven, Neth.},
     1975    address     = {Eindhoven, Netherlands},
    19761976    year        = 1965,
    19771977    note        = {Reprinted in \cite{Genuys68} pp. 43--112.}
  • doc/papers/concurrency/Paper.tex

    r223a633 r33c3ded  
    224224{}
    225225\lstnewenvironment{C++}[1][]                            % use C++ style
    226 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
     226{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
    227227{}
    228228\lstnewenvironment{uC++}[1][]
    229 {\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
     229{\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
    230230{}
    231231\lstnewenvironment{Go}[1][]
    232 {\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
     232{\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
    233233{}
    234234\lstnewenvironment{python}[1][]
    235 {\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
     235{\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
    236236{}
    237237\lstnewenvironment{java}[1][]
    238 {\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
     238{\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
    239239{}
    240240
     
    284284
    285285\begin{document}
    286 %\linenumbers                           % comment out to turn off line numbering
     286\linenumbers                            % comment out to turn off line numbering
    287287
    288288\maketitle
     
    450450\hline
    451451stateful                        & thread        & \multicolumn{1}{c|}{No} & \multicolumn{1}{c}{Yes} \\
    452 \hline
    453 \hline
     452\hline   
     453\hline   
    454454No                                      & No            & \textbf{1}\ \ \ @struct@                              & \textbf{2}\ \ \ @mutex@ @struct@              \\
    455 \hline
     455\hline   
    456456Yes (stackless)         & No            & \textbf{3}\ \ \ @generator@                   & \textbf{4}\ \ \ @mutex@ @generator@   \\
    457 \hline
     457\hline   
    458458Yes (stackful)          & No            & \textbf{5}\ \ \ @coroutine@                   & \textbf{6}\ \ \ @mutex@ @coroutine@   \\
    459 \hline
     459\hline   
    460460No                                      & Yes           & \textbf{7}\ \ \ {\color{red}rejected} & \textbf{8}\ \ \ {\color{red}rejected} \\
    461 \hline
     461\hline   
    462462Yes (stackless)         & Yes           & \textbf{9}\ \ \ {\color{red}rejected} & \textbf{10}\ \ \ {\color{red}rejected} \\
    463 \hline
     463\hline   
    464464Yes (stackful)          & Yes           & \textbf{11}\ \ \ @thread@                             & \textbf{12}\ \ @mutex@ @thread@               \\
    465465\end{tabular}
     
    28962896\label{s:RuntimeStructureCluster}
    28972897
    2898 A \newterm{cluster} is a collection of user and kernel threads, where the kernel threads run the user threads from the cluster's ready queue, and the operating system runs the kernel threads on the processors from its ready queue~\cite{Buhr90a}.
     2898A \newterm{cluster} is a collection of user and kernel threads, where the kernel threads run the user threads from the cluster's ready queue, and the operating system runs the kernel threads on the processors from its ready queue.
    28992899The term \newterm{virtual processor} is introduced as a synonym for kernel thread to disambiguate between user and kernel thread.
    29002900From the language perspective, a virtual processor is an actual processor (core).
     
    29922992\end{cfa}
    29932993where CPU time in nanoseconds is from the appropriate language clock.
    2994 Each benchmark is performed @N@ times, where @N@ is selected so the benchmark runs in the range of 2--20 seconds for the specific programming language;
    2995 each @N@ appears after the experiment name in the following tables.
     2994Each benchmark is performed @N@ times, where @N@ is selected so the benchmark runs in the range of 2--20 seconds for the specific programming language.
    29962995The total time is divided by @N@ to obtain the average time for a benchmark.
    29972996Each benchmark experiment is run 13 times and the average appears in the table.
    2998 For languages with a runtime JIT (Java, Node.js, Python), a single half-hour long experiment is run to check stability;
    2999 all long-experiment results are statistically equivalent, \ie median/average/standard-deviation correlate with the short-experiment results, indicating the short experiments reached a steady state.
    30002997All omitted tests for other languages are functionally identical to the \CFA tests and available online~\cite{CforallConcurrentBenchmarks}.
     2998% tar --exclude-ignore=exclude -cvhf benchmark.tar benchmark
     2999% cp -p benchmark.tar /u/cforall/public_html/doc/concurrent_benchmark.tar
    30013000
    30023001\paragraph{Creation}
     
    30073006
    30083007\begin{multicols}{2}
    3009 \begin{cfa}[xleftmargin=0pt]
    3010 `coroutine` MyCoroutine {};
     3008\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     3009\begin{cfa}
     3010@coroutine@ MyCoroutine {};
    30113011void ?{}( MyCoroutine & this ) {
    30123012#ifdef EAGER
     
    30163016void main( MyCoroutine & ) {}
    30173017int main() {
    3018         BENCH( for ( N ) { `MyCoroutine c;` } )
     3018        BENCH( for ( N ) { @MyCoroutine c;@ } )
    30193019        sout | result;
    30203020}
     
    30303030
    30313031\begin{tabular}[t]{@{}r*{3}{D{.}{.}{5.2}}@{}}
    3032 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3033 \CFA generator (1B)                     & 0.6           & 0.6           & 0.0           \\
    3034 \CFA coroutine lazy     (100M)  & 13.4          & 13.1          & 0.5           \\
    3035 \CFA coroutine eager (10M)      & 144.7         & 143.9         & 1.5           \\
    3036 \CFA thread (10M)                       & 466.4         & 468.0         & 11.3          \\
    3037 \uC coroutine (10M)                     & 155.6         & 155.7         & 1.7           \\
    3038 \uC thread (10M)                        & 523.4         & 523.9         & 7.7           \\
    3039 Python generator (10M)          & 123.2         & 124.3         & 4.1           \\
    3040 Node.js generator (10M)         & 33.4          & 33.5          & 0.3           \\
    3041 Goroutine thread (10M)          & 751.0         & 750.5         & 3.1           \\
    3042 Rust tokio thread (10M)         & 1860.0        & 1881.1        & 37.6          \\
    3043 Rust thread     (250K)                  & 53801.0       & 53896.8       & 274.9         \\
    3044 Java thread (250K)                      & 119256.0      & 119679.2      & 2244.0        \\
    3045 % Java thread (1 000 000)               & 123100.0      & 123052.5      & 751.6         \\
    3046 Pthreads thread (250K)          & 31465.5       & 31419.5       & 140.4
     3032\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3033\CFA generator                  & 0.6           & 0.6           & 0.0           \\
     3034\CFA coroutine lazy             & 13.4          & 13.1          & 0.5           \\
     3035\CFA coroutine eager    & 144.7         & 143.9         & 1.5           \\
     3036\CFA thread                             & 466.4         & 468.0         & 11.3          \\
     3037\uC coroutine                   & 155.6         & 155.7         & 1.7           \\
     3038\uC thread                              & 523.4         & 523.9         & 7.7           \\
     3039Python generator                & 123.2         & 124.3         & 4.1           \\
     3040Node.js generator               & 33.4          & 33.5          & 0.3           \\
     3041Goroutine thread                & 751.0         & 750.5         & 3.1           \\
     3042Rust tokio thread               & 1860.0        & 1881.1        & 37.6          \\
     3043Rust thread                             & 53801.0       & 53896.8       & 274.9         \\
     3044Java thread                             & 120274.0      & 120722.9      & 2356.7        \\
     3045Pthreads thread                 & 31465.5       & 31419.5       & 140.4
    30473046\end{tabular}
    30483047\end{multicols}
     
    30533052Internal scheduling is measured using a cycle of two threads signalling and waiting.
    30543053Figure~\ref{f:schedint} shows the code for \CFA, with results in Table~\ref{t:schedint}.
    3055 Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects.
    3056 User-level threading has one kernel thread, eliminating contention between the threads (direct handoff of the kernel thread).
    3057 Kernel-level threading has two kernel threads allowing some contention.
     3054Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
     3055Java scheduling is significantly greater because the benchmark explicitly creates multiple threads in order to prevent the JIT from making the program sequential, \ie removing all locking.
    30583056
    30593057\begin{multicols}{2}
    3060 \setlength{\tabcolsep}{3pt}
    3061 \begin{cfa}[xleftmargin=0pt]
     3058\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     3059\begin{cfa}
    30623060volatile int go = 0;
    3063 `condition c;`
    3064 `monitor` M {} m1/*, m2, m3, m4*/;
    3065 void call( M & `mutex p1/*, p2, p3, p4*/` ) {
    3066         `signal( c );`
    3067 }
    3068 void wait( M & `mutex p1/*, p2, p3, p4*/` ) {
     3061@condition c;@
     3062@monitor@ M {} m1/*, m2, m3, m4*/;
     3063void call( M & @mutex p1/*, p2, p3, p4*/@ ) {
     3064        @signal( c );@
     3065}
     3066void wait( M & @mutex p1/*, p2, p3, p4*/@ ) {
    30693067        go = 1; // continue other thread
    3070         for ( N ) { `wait( c );` } );
     3068        for ( N ) { @wait( c );@ } );
    30713069}
    30723070thread T {};
     
    30933091
    30943092\begin{tabular}{@{}r*{3}{D{.}{.}{5.2}}@{}}
    3095 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3096 \CFA @signal@, 1 monitor (10M)  & 364.4         & 364.2         & 4.4           \\
    3097 \CFA @signal@, 2 monitor (10M)  & 484.4         & 483.9         & 8.8           \\
    3098 \CFA @signal@, 4 monitor (10M)  & 709.1         & 707.7         & 15.0          \\
    3099 \uC @signal@ monitor (10M)              & 328.3         & 327.4         & 2.4           \\
    3100 Rust cond. variable     (1M)            & 7514.0        & 7437.4        & 397.2         \\
    3101 Java @notify@ monitor (1M)              & 8717.0        & 8774.1        & 471.8         \\
    3102 % Java @notify@ monitor (100 000 000)           & 8634.0        & 8683.5        & 330.5         \\
    3103 Pthreads cond. variable (1M)    & 5553.7        & 5576.1        & 345.6
     3093\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} & \multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3094\CFA @signal@, 1 monitor        & 364.4         & 364.2         & 4.4           \\
     3095\CFA @signal@, 2 monitor        & 484.4         & 483.9         & 8.8           \\
     3096\CFA @signal@, 4 monitor        & 709.1         & 707.7         & 15.0          \\
     3097\uC @signal@ monitor            & 328.3         & 327.4         & 2.4           \\
     3098Rust cond. variable                     & 7514.0        & 7437.4        & 397.2         \\
     3099Java @notify@ monitor           & 9623.0        & 9654.6        & 236.2         \\
     3100Pthreads cond. variable         & 5553.7        & 5576.1        & 345.6
    31043101\end{tabular}
    31053102\end{multicols}
     
    31103107External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement.
    31113108Figure~\ref{f:schedext} shows the code for \CFA with results in Table~\ref{t:schedext}.
    3112 Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects.
     3109Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    31133110
    31143111\begin{multicols}{2}
    3115 \setlength{\tabcolsep}{5pt}
     3112\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    31163113\vspace*{-16pt}
    3117 \begin{cfa}[xleftmargin=0pt]
    3118 `monitor` M {} m1/*, m2, m3, m4*/;
    3119 void call( M & `mutex p1/*, p2, p3, p4*/` ) {}
    3120 void wait( M & `mutex p1/*, p2, p3, p4*/` ) {
    3121         for ( N ) { `waitfor( call : p1/*, p2, p3, p4*/ );` }
     3114\begin{cfa}
     3115@monitor@ M {} m1/*, m2, m3, m4*/;
     3116void call( M & @mutex p1/*, p2, p3, p4*/@ ) {}
     3117void wait( M & @mutex p1/*, p2, p3, p4*/@ ) {
     3118        for ( N ) { @waitfor( call : p1/*, p2, p3, p4*/ );@ }
    31223119}
    31233120thread T {};
     
    31363133\columnbreak
    31373134
    3138 \vspace*{-18pt}
     3135\vspace*{-16pt}
    31393136\captionof{table}{External-scheduling comparison (nanoseconds)}
    31403137\label{t:schedext}
    31413138\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3142 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3143 \CFA @waitfor@, 1 monitor (10M) & 367.1 & 365.3 & 5.0   \\
    3144 \CFA @waitfor@, 2 monitor (10M) & 463.0 & 464.6 & 7.1   \\
    3145 \CFA @waitfor@, 4 monitor (10M) & 689.6 & 696.2 & 21.5  \\
    3146 \uC \lstinline[language=uC++]|_Accept| monitor (10M)    & 328.2 & 329.1 & 3.4   \\
    3147 Go \lstinline[language=Golang]|select| channel (10M)    & 365.0 & 365.5 & 1.2
     3139\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3140\CFA @waitfor@, 1 monitor       & 367.1 & 365.3 & 5.0   \\
     3141\CFA @waitfor@, 2 monitor       & 463.0 & 464.6 & 7.1   \\
     3142\CFA @waitfor@, 4 monitor       & 689.6 & 696.2 & 21.5  \\
     3143\uC \lstinline[language=uC++]|_Accept| monitor  & 328.2 & 329.1 & 3.4   \\
     3144Go \lstinline[language=Golang]|select| channel  & 365.0 & 365.5 & 1.2
    31483145\end{tabular}
    31493146\end{multicols}
     
    31583155
    31593156\begin{multicols}{2}
    3160 \setlength{\tabcolsep}{3pt}
    3161 \begin{cfa}[xleftmargin=0pt]
    3162 `monitor` M {} m1/*, m2, m3, m4*/;
    3163 call( M & `mutex p1/*, p2, p3, p4*/` ) {}
     3157\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     3158\begin{cfa}
     3159@monitor@ M {} m1/*, m2, m3, m4*/;
     3160call( M & @mutex p1/*, p2, p3, p4*/@ ) {}
    31643161int main() {
    31653162        BENCH( for( N ) call( m1/*, m2, m3, m4*/ ); )
     
    31763173\label{t:mutex}
    31773174\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3178 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3179 test-and-test-set lock (50M)            & 19.1  & 18.9  & 0.4   \\
    3180 \CFA @mutex@ function, 1 arg. (50M)     & 48.3  & 47.8  & 0.9   \\
    3181 \CFA @mutex@ function, 2 arg. (50M)     & 86.7  & 87.6  & 1.9   \\
    3182 \CFA @mutex@ function, 4 arg. (50M)     & 173.4 & 169.4 & 5.9   \\
    3183 \uC @monitor@ member rtn. (50M)         & 54.8  & 54.8  & 0.1   \\
    3184 Goroutine mutex lock (50M)                      & 34.0  & 34.0  & 0.0   \\
    3185 Rust mutex lock (50M)                           & 33.0  & 33.2  & 0.8   \\
    3186 Java synchronized method (50M)          & 31.0  & 30.9  & 0.5   \\
    3187 % Java synchronized method (10 000 000 000)             & 31.0 & 30.2 & 0.9 \\
    3188 Pthreads mutex Lock (50M)                       & 31.0  & 31.1  & 0.4
     3175\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3176test-and-test-set lock                  & 19.1  & 18.9  & 0.4   \\
     3177\CFA @mutex@ function, 1 arg.   & 48.3  & 47.8  & 0.9   \\
     3178\CFA @mutex@ function, 2 arg.   & 86.7  & 87.6  & 1.9   \\
     3179\CFA @mutex@ function, 4 arg.   & 173.4 & 169.4 & 5.9   \\
     3180\uC @monitor@ member rtn.               & 54.8  & 54.8  & 0.1   \\
     3181Goroutine mutex lock                    & 34.0  & 34.0  & 0.0   \\
     3182Rust mutex lock                                 & 33.0  & 33.2  & 0.8   \\
     3183Java synchronized method                & 31.0  & 31.0  & 0.0   \\
     3184Pthreads mutex Lock                             & 31.0  & 31.1  & 0.4
    31893185\end{tabular}
    31903186\end{multicols}
     
    32053201% To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca>
    32063202% Date: Fri, 24 Jan 2020 13:49:18 -0500
    3207 %
     3203% 
    32083204% I can also verify that the previous version, which just tied a bunch of promises together, *does not* go back to the
    32093205% event loop at all in the current version of Node. Presumably they're taking advantage of the fact that the ordering of
     
    32153211
    32163212\begin{multicols}{2}
    3217 \begin{cfa}[xleftmargin=0pt]
    3218 `coroutine` C {};
    3219 void main( C & ) { for () { `suspend;` } }
     3213\lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     3214\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     3215@coroutine@ C {};
     3216void main( C & ) { for () { @suspend;@ } }
    32203217int main() { // coroutine test
    32213218        C c;
    3222         BENCH( for ( N ) { `resume( c );` } )
     3219        BENCH( for ( N ) { @resume( c );@ } )
    32233220        sout | result;
    32243221}
    32253222int main() { // thread test
    3226         BENCH( for ( N ) { `yield();` } )
     3223        BENCH( for ( N ) { @yield();@ } )
    32273224        sout | result;
    32283225}
     
    32373234\label{t:ctx-switch}
    32383235\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3239 \multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3240 C function (10B)                        & 1.8           & 1.8           & 0.0   \\
    3241 \CFA generator (5B)                     & 1.8           & 2.0           & 0.3   \\
    3242 \CFA coroutine (100M)           & 32.5          & 32.9          & 0.8   \\
    3243 \CFA thread (100M)                      & 93.8          & 93.6          & 2.2   \\
    3244 \uC coroutine (100M)            & 50.3          & 50.3          & 0.2   \\
    3245 \uC thread (100M)                       & 97.3          & 97.4          & 1.0   \\
    3246 Python generator (100M)         & 40.9          & 41.3          & 1.5   \\
    3247 Node.js await (5M)                      & 1852.2        & 1854.7        & 16.4  \\
    3248 Node.js generator (100M)        & 33.3          & 33.4          & 0.3   \\
    3249 Goroutine thread (100M)         & 143.0         & 143.3         & 1.1   \\
    3250 Rust async await (100M)         & 32.0          & 32.0          & 0.0   \\
    3251 Rust tokio thread (100M)        & 143.0         & 143.0         & 1.7   \\
    3252 Rust thread (25M)                       & 332.0         & 331.4         & 2.4   \\
    3253 Java thread (100M)                      & 405.0         & 415.0         & 17.6  \\
    3254 % Java thread (  100 000 000)                   & 413.0 & 414.2 & 6.2 \\
    3255 % Java thread (5 000 000 000)                   & 415.0 & 415.2 & 6.1 \\
    3256 Pthreads thread (25M)           & 334.3         & 335.2         & 3.9
     3236\multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3237C function                      & 1.8           & 1.8           & 0.0   \\
     3238\CFA generator          & 1.8           & 2.0           & 0.3   \\
     3239\CFA coroutine          & 32.5          & 32.9          & 0.8   \\
     3240\CFA thread                     & 93.8          & 93.6          & 2.2   \\
     3241\uC coroutine           & 50.3          & 50.3          & 0.2   \\
     3242\uC thread                      & 97.3          & 97.4          & 1.0   \\
     3243Python generator        & 40.9          & 41.3          & 1.5   \\
     3244Node.js await           & 1852.2        & 1854.7        & 16.4  \\
     3245Node.js generator       & 33.3          & 33.4          & 0.3   \\
     3246Goroutine thread        & 143.0         & 143.3         & 1.1   \\
     3247Rust async await        & 32.0          & 32.0          & 0.0   \\
     3248Rust tokio thread       & 143.0         & 143.0         & 1.7   \\
     3249Rust thread                     & 332.0         & 331.4         & 2.4   \\
     3250Java thread                     & 405.0         & 415.0         & 17.6  \\
     3251Pthreads thread         & 334.3         & 335.2         & 3.9
    32573252\end{tabular}
    32583253\end{multicols}
     
    32633258Languages using 1:1 threading based on pthreads can at best meet or exceed, due to language overhead, the pthread results.
    32643259Note, pthreads has a fast zero-contention mutex lock checked in user space.
    3265 Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions (context-switching or locking).
    3266 As well, for locking experiments, M:N threading has less contention if only one kernel thread is used.
     3260Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions.
    32673261Languages with stackful coroutines have higher cost than stackless coroutines because of stack allocation and context switching;
    32683262however, stackful \uC and \CFA coroutines have approximately the same performance as stackless Python and Node.js generators.
    32693263The \CFA stackless generator is approximately 25 times faster for suspend/resume and 200 times faster for creation than stackless Python and Node.js generators.
    3270 The Node.js context-switch is costly when asynchronous await must enter the event engine because a promise is not fulfilled.
    3271 Finally, the benchmark results correlate across programming languages with and without JIT, indicating the JIT has completed any runtime optimizations.
    32723264
    32733265
     
    33273319
    33283320The authors recognize the design assistance of Aaron Moss, Rob Schluntz, Andrew Beach, and Michael Brooks; David Dice for commenting and helping with the Java benchmarks; and Gregor Richards for helping with the Node.js benchmarks.
    3329 This research is funded by the NSERC/Waterloo-Huawei (\url{http://www.huawei.com}) Joint Innovation Lab. %, and Peter Buhr is partially funded by the Natural Sciences and Engineering Research Council of Canada.
     3321This research is funded by a grant from Waterloo-Huawei (\url{http://www.huawei.com}) Joint Innovation Lab. %, and Peter Buhr is partially funded by the Natural Sciences and Engineering Research Council of Canada.
    33303322
    33313323{%
  • doc/papers/concurrency/annex/local.bib

    r223a633 r33c3ded  
    5959@manual{Cpp-Transactions,
    6060        keywords        = {C++, Transactional Memory},
    61         title           = {Tech. Spec. for C++ Extensions for Transactional Memory},
     61        title           = {Technical Specification for C++ Extensions for Transactional Memory},
    6262        organization= {International Standard ISO/IEC TS 19841:2015 },
    6363        publisher   = {American National Standards Institute},
  • doc/papers/concurrency/mail2

    r223a633 r33c3ded  
    959959Software: Practice and Experience Editorial Office
    960960
    961 
    962 
    963 Date: Wed, 2 Sep 2020 20:55:34 +0000
    964 From: Richard Jones <onbehalfof@manuscriptcentral.com>
    965 Reply-To: R.E.Jones@kent.ac.uk
    966 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
    967 Subject: Software: Practice and Experience - Decision on Manuscript ID
    968  SPE-19-0219.R2
    969 
    970 02-Sep-2020
    971 
    972 Dear Dr Buhr,
    973 
    974 Many thanks for submitting SPE-19-0219.R2 entitled "Advanced Control-flow and Concurrency in Cforall" to Software: Practice and Experience. The paper has now been reviewed and the comments of the referees are included at the bottom of this letter. I apologise for the length of time it has taken to get these.
    975 
    976 Both reviewers consider this paper to be close to acceptance. However, before I can accept this paper, I would like you address the comments of Reviewer 2, particularly with regard to the description of the adaptation Java harness to deal with warmup. I would expect to see a convincing argument that the computation has reached a steady state. I would also like you to provide the values for N for each benchmark run. This should be very straightforward for you to do. There are a couple of papers on steady state that you may wish to consult (though I am certainly not pushing my own work).
    977 
    978 1) Barrett, Edd; Bolz-Tereick, Carl Friedrich; Killick, Rebecca; Mount, Sarah and Tratt, Laurence. Virtual Machine Warmup Blows Hot and Cold. OOPSLA 2017. https://doi.org/10.1145/3133876
    979 Virtual Machines (VMs) with Just-In-Time (JIT) compilers are traditionally thought to execute programs in two phases: the initial warmup phase determines which parts of a program would most benefit from dynamic compilation, before JIT compiling those parts into machine code; subsequently the program is said to be at a steady state of peak performance. Measurement methodologies almost always discard data collected during the warmup phase such that reported measurements focus entirely on peak performance. We introduce a fully automated statistical approach, based on changepoint analysis, which allows us to determine if a program has reached a steady state and, if so, whether that represents peak performance or not. Using this, we show that even when run in the most controlled of circumstances, small, deterministic, widely studied microbenchmarks often fail to reach a steady state of peak performance on a variety of common VMs. Repeating our experiment on 3 different machines, we found that at most 43.5% of pairs consistently reach a steady state of peak performance.
    980 
    981 2) Kalibera, Tomas and Jones, Richard. Rigorous Benchmarking in Reasonable Time. ISMM  2013. https://doi.org/10.1145/2555670.2464160
    982 Experimental evaluation is key to systems research. Because modern systems are complex and non-deterministic, good experimental methodology demands that researchers account for uncertainty. To obtain valid results, they are expected to run many iterations of benchmarks, invoke virtual machines (VMs) several times, or even rebuild VM or benchmark binaries more than once. All this repetition costs time to complete experiments. Currently, many evaluations give up on sufficient repetition or rigorous statistical methods, or even run benchmarks only in training sizes. The results reported often lack proper variation estimates and, when a small difference between two systems is reported, some are simply unreliable.In contrast, we provide a statistically rigorous methodology for repetition and summarising results that makes efficient use of experimentation time. Time efficiency comes from two key observations. First, a given benchmark on a given platform is typically prone to much less non-determinism than the common worst-case of published corner-case studies. Second, repetition is most needed where most uncertainty arises (whether between builds, between executions or between iterations). We capture experimentation cost with a novel mathematical model, which we use to identify the number of repetitions at each level of an experiment necessary and sufficient to obtain a given level of precision.We present our methodology as a cookbook that guides researchers on the number of repetitions they should run to obtain reliable results. We also show how to present results with an effect size confidence interval. As an example, we show how to use our methodology to conduct throughput experiments with the DaCapo and SPEC CPU benchmarks on three recent platforms.
    983 
    984 You have 42 days from the date of this email to submit your revision. If you are unable to complete the revision within this time, please contact me to request a short extension.
    985 
    986 You can upload your revised manuscript and submit it through your Author Center. Log into https://mc.manuscriptcentral.com/spe and enter your Author Center, where you will find your manuscript title listed under "Manuscripts with Decisions".
    987 
    988 When submitting your revised manuscript, you will be able to respond to the comments made by the referee(s) in the space provided.  You can use this space to document any changes you make to the original manuscript.
    989 
    990 If you would like help with English language editing, or other article preparation support, Wiley Editing Services offers expert help with English Language Editing, as well as translation, manuscript formatting, and figure formatting at www.wileyauthors.com/eeo/preparation. You can also check out our resources for Preparing Your Article for general guidance about writing and preparing your manuscript at www.wileyauthors.com/eeo/prepresources.
    991  
    992 Once again, thank you for submitting your manuscript to Software: Practice and Experience. I look forward to receiving your revision.
    993 
    994 Sincerely,
    995 Richard
    996 
    997 Prof. Richard Jones
    998 Editor, Software: Practice and Experience
    999 R.E.Jones@kent.ac.uk
    1000 
    1001 Referee(s)' Comments to Author:
    1002 
    1003 Reviewing: 1
    1004 
    1005 Comments to the Author
    1006 Overall, I felt that this draft was an improvement on previous drafts and I don't have further changes to request.
    1007 
    1008 I appreciated the new language to clarify the relationship of external and internal scheduling, for example, as well as the new measurements of Rust tokio. Also, while I still believe that the choice between thread/generator/coroutine and so forth could be made crisper and clearer, the current draft of Section 2 did seem adequate to me in terms of specifying the considerations that users would have to take into account to make the choice.
    1009 
    1010 
    1011 Reviewing: 2
    1012 
    1013 Comments to the Author
    1014 First: let me apologise for the delay on this review. I'll blame the global pandemic combined with my institution's senior management's counterproductive decisions for taking up most of my time and all of my energy.
    1015 
    1016 At this point, reading the responses, I think we've been around the course enough times that further iteration is unlikely to really improve the paper any further, so I'm happy to recommend acceptance.    My main comments are that there were some good points in the responses to *all* the reviews and I strongly encourage the authors to incorporate those discursive responses into the final paper so they may benefit readers as well as reviewers.   I agree with the recommendations of reviewer #2 that the paper could usefully be split in to two, which I think I made to a previous revision, but I'm happy to leave that decision to the Editor.
    1017 
    1018 Finally, the paper needs to describe how the Java harness was adapted to deal with warmup; why the computation has warmed up and reached a steady state - similarly for js and Python. The tables should also give the "N" chosen for each benchmark run.
    1019  
    1020 minor points
    1021 * don't start sentences with "However"
    1022 * most downloaded isn't an "Award"
    1023 
    1024 
    1025 
    1026 Date: Thu, 1 Oct 2020 05:34:29 +0000
    1027 From: Richard Jones <onbehalfof@manuscriptcentral.com>
    1028 Reply-To: R.E.Jones@kent.ac.uk
    1029 To: pabuhr@uwaterloo.ca
    1030 Subject: Revision reminder - SPE-19-0219.R2
    1031 
    1032 01-Oct-2020
    1033 
    1034 Dear Dr Buhr
    1035 
    1036 SPE-19-0219.R2
    1037 
    1038 This is a reminder that your opportunity to revise and re-submit your manuscript will expire 14 days from now. If you require more time please contact me directly and I may grant an extension to this deadline, otherwise the option to submit a revision online, will not be available.
    1039 
    1040 If your article is of potential interest to the general public, (which means it must be timely, groundbreaking, interesting and impact on everyday society) then please e-mail ejp@wiley.co.uk explaining the public interest side of the research. Wiley will then investigate the potential for undertaking a global press campaign on the article.
    1041 
    1042 I look forward to receiving your revision.
    1043 
    1044 Sincerely,
    1045 
    1046 Prof. Richard Jones
    1047 Editor, Software: Practice and Experience
    1048 
    1049 https://mc.manuscriptcentral.com/spe
    1050 
    1051 
    1052 
    1053 Date: Tue, 6 Oct 2020 15:29:41 +0000
    1054 From: Mayank Roy Chowdhury <onbehalfof@manuscriptcentral.com>
    1055 Reply-To: speoffice@wiley.com
    1056 To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
    1057 Subject: SPE-19-0219.R3 successfully submitted
    1058 
    1059 06-Oct-2020
    1060 
    1061 Dear Dr Buhr,
    1062 
    1063 Your manuscript entitled "Advanced Control-flow and Concurrency in Cforall" has been successfully submitted online and is presently being given full consideration for publication in Software: Practice and Experience.
    1064 
    1065 Your manuscript number is SPE-19-0219.R3.  Please mention this number in all future correspondence regarding this submission.
    1066 
    1067 You can view the status of your manuscript at any time by checking your Author Center after logging into https://mc.manuscriptcentral.com/spe.  If you have difficulty using this site, please click the 'Get Help Now' link at the top right corner of the site.
    1068 
    1069 
    1070 Thank you for submitting your manuscript to Software: Practice and Experience.
    1071 
    1072 Sincerely,
    1073 
    1074 Software: Practice and Experience Editorial Office
    1075 
  • doc/refrat/refrat.tex

    r223a633 r33c3ded  
    1111%% Created On       : Wed Apr  6 14:52:25 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Mon Oct  5 09:02:53 2020
    14 %% Update Count     : 110
     13%% Last Modified On : Wed Jan 31 17:30:23 2018
     14%% Update Count     : 108
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
     32\usepackage{xspace}
    3233\usepackage{varioref}                                                                   % extended references
     34\usepackage{listings}                                                                   % format program code
    3335\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3436\usepackage{latexsym}                                   % \Box glyph
    3537\usepackage{mathptmx}                                   % better math font with "times"
    3638\usepackage[usenames]{color}
    37 \newcommand{\CFALatin}{}
     39\input{common}                                          % common CFA document macros
     40\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
     41\usepackage{breakurl}
     42\renewcommand{\UrlFont}{\small\sf}
     43
     44\usepackage[pagewise]{lineno}
     45\renewcommand{\linenumberfont}{\scriptsize\sffamily}
     46\usepackage[firstpage]{draftwatermark}
     47\SetWatermarkLightness{0.9}
     48
     49% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     50% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     51% AFTER HYPERREF.
     52\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     53
     54\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     55\setlength{\headsep}{0.25in}
     56
     57%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     58
     59\CFAStyle                                                                                               % use default CFA format-style
     60\lstnewenvironment{C++}[1][]                            % use C++ style
     61{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®}#1}}
     62{}
     63
    3864% inline code ©...© (copyright symbol) emacs: C-q M-)
    3965% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    4369% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    4470% math escape $...$ (dollar symbol)
    45 \input{common}                                          % common CFA document macros
    46 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    47 \usepackage{breakurl}
    48 \renewcommand{\UrlFont}{\small\sf}
    49 
    50 \usepackage[pagewise]{lineno}
    51 \renewcommand{\linenumberfont}{\scriptsize\sffamily}
    52 \usepackage[firstpage]{draftwatermark}
    53 \SetWatermarkLightness{0.9}
    54 
    55 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    56 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    57 % AFTER HYPERREF.
    58 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    59 
    60 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
    61 \setlength{\headsep}{0.25in}
    6271
    6372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    6473
    65 \CFAStyle                                                                                               % use default CFA format-style
    66 \lstnewenvironment{C++}[1][]                            % use C++ style
    67 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
    68 {}
    69 
    70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    71 
    7274% Names used in the document.
    73 \newcommand{\Version}{\input{build/version}}
     75\newcommand{\Version}{\input{../../version}}
    7476\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    7577\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
  • doc/theses/andrew_beach_MMath/thesis.tex

    r223a633 r33c3ded  
    3434\usepackage[toc,abbreviations]{glossaries-extra}
    3535
    36 % Define all the glossaries.
    37 \input{glossaries}
     36% Main glossary entries -- definitions of relevant terminology
     37\newglossaryentry{computer}
     38{
     39name=computer,
     40description={A programmable machine that receives input data,
     41               stores and manipulates the data, and provides
     42               formatted output}
     43}
     44
     45% Nomenclature glossary entries -- New definitions, or unusual terminology
     46\newglossary*{nomenclature}{Nomenclature}
     47\newglossaryentry{dingledorf}
     48{
     49type=nomenclature,
     50name=dingledorf,
     51description={A person of supposed average intelligence who makes incredibly
     52               brainless misjudgments}
     53}
     54
     55% List of Abbreviations (abbreviations are from the glossaries-extra package)
     56\newabbreviation{aaaaz}{AAAAZ}{American Association of Amature Astronomers
     57               and Zoologists}
     58
     59% List of Symbols
     60\newglossary*{symbols}{List of Symbols}
     61\newglossaryentry{rvec}
     62{
     63name={$\mathbf{v}$},
     64sort={label},
     65type=symbols,
     66description={Random vector: a location in n-dimensional Cartesian space, where
     67               each dimensional component is determined by a random process}
     68}
    3869
    3970% Generate the glossaries defined above.
  • doc/theses/fangren_yu_COOP_S20/Makefile

    r223a633 r33c3ded  
    4646# File Dependencies #
    4747
     48
    4849${DOCUMENT} : ${BASE}.ps
    4950        ps2pdf $<
  • doc/theses/fangren_yu_COOP_S20/Report.tex

    r223a633 r33c3ded  
    1 \documentclass[twoside,11pt]{article}
     1\documentclass[twoside,12pt]{article}
    22
    33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    1111\usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig}
    1212\renewcommand{\thesubfigure}{\alph{subfigure})}
    13 \usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    1413\usepackage{latexsym}                                   % \Box glyph
    1514\usepackage{mathptmx}                                   % better math font with "times"
    16 \usepackage[toc]{appendix}                                                              % article does not have appendix
    1715\usepackage[usenames]{color}
    1816\input{common}                                          % common CFA document macros
    1917\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    2018\usepackage{breakurl}
    21 \urlstyle{sf}
    22 
    23 % reduce spacing
    24 \setlist[itemize]{topsep=5pt,parsep=0pt}% global
    25 \setlist[enumerate]{topsep=5pt,parsep=0pt}% global
    2619
    2720\usepackage[pagewise]{lineno}
     
    3326\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    3427\newcommand{\NOTE}{\textbf{NOTE}}
    35 \newcommand{\TODO}[1]{{\color{Purple}#1}}
    3628
    3729\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     
    4032%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    4133
    42 \CFAStyle                                                                                               % CFA code-style for all languages
     34\CFADefaults
    4335\lstset{
    44 language=C++,moredelim=**[is][\color{red}]{@}{@}                % make C++ the default language
     36language=C++,                                                                                   % make C++ the default language
     37escapechar=\$,                                                                                  % LaTeX escape in CFA code
     38moredelim=**[is][\color{red}]{`}{`},
    4539}% lstset
     40\lstMakeShortInline@%
    4641\lstnewenvironment{C++}[1][]                            % use C++ style
    47 {\lstset{language=C++,moredelim=**[is][\color{red}]{@}{@}}\lstset{#1}}{}
     42{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}}
     43{}
    4844
    4945%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    8884\section{Overview}
    8985
    90 @cfa-cc@ is the reference compiler for the \CFA programming language, which is a non-object-oriented extension to C.
    91 \CFA attempts to introduce productive modern programming language features to C while maintaining as much backward-compatibility as possible, so that most existing C programs can seamlessly work with \CFA.
    92 
    93 Since the \CFA project dates back to the early 2000s, and only restarted in the past few years, there is a significant amount of legacy code in the current compiler codebase with little documentation.
    94 The lack of documentation makes it difficult to develop new features from the current implementation and diagnose problems.
    95 
    96 Currently, the \CFA team is also facing poor compiler performance.
    97 For the development of a new programming language, writing standard libraries is an important component.
    98 The slow compiler causes building of the library files to take tens of minutes, making iterative development and testing almost impossible.
    99 There is an ongoing effort to rewrite the core data-structure of the compiler to overcome the performance issue, but many bugs have appeared during this work, and lack of documentation is hampering debugging.
    100 
    101 This developer's reference manual begins the documentation and should be continuously im\-proved until it eventually covers the entire compiler codebase.
    102 For now, the focus is mainly on the parts being rewritten, and also the primary performance bottleneck, namely the resolution algorithm.
    103 Its aimed is to provide new project developers with guidance in understanding the codebase, and clarify the purpose and behaviour of certain functions that are not mentioned in the previous \CFA research papers~\cite{Bilson03,Ditchfield92,Moss19}.
     86cfa-cc is the reference compiler for the \CFA programming language, which is a non-
     87object-oriented extension to C.
     88\CFA attempts to introduce productive modern programming language features to C
     89while maintaining as much backward-compatibility as possible, so that most existing C
     90programs can seamlessly work with \CFA.
     91
     92Since the \CFA project was dated back to the early 2000s, and only restarted in the past
     93few years, there is a significant amount of legacy code in the current compiler codebase,
     94with little proper documentation available. This becomes a difficulty while developing new
     95features based on the previous implementations, and especially while diagnosing
     96problems.
     97
     98Currently, the \CFA team is also facing another problem: bad compiler performance. For
     99the development of a new programming language, writing a standard library is an
     100important part. The incompetence of the compiler causes building the library files to take
     101tens of minutes, making iterative development and testing almost impossible. There is
     102ongoing effort to rewrite the core data structure of the compiler to overcome the
     103performance issue, but many bugs may appear during the work, and lack of documentation
     104makes debugging extremely difficult.
     105
     106This developer's reference will be continuously improved and eventually cover the
     107compiler codebase. For now, the focus is mainly on the parts being rewritten, and also the
     108performance bottleneck, namely the resolution algorithm. It is aimed to provide new
     109developers to the project enough guidance and clarify the purposes and behavior of certain
     110functions which are not mentioned in the previous \CFA research papers.
    104111
    105112
    106113\section{Compiler Framework}
    107114
    108 \CFA source code is first transformed into an abstract syntax tree (AST) by the parser before analyzed by the compiler.
    109 
    110 
    111115\subsection{AST Representation}
    112116
    113 
    114 There are 4 major categories of AST nodes used by the compiler, along with some derived structures.
    115 
    116 \subsubsection{Declaration Nodes}
     117Source code input is first transformed into abstract syntax tree (AST) representation by the
     118parser before analyzed by the compiler.
     119
     120There are 4 major categories of AST nodes used by the compiler, along with some derived
     121structures.
     122
     123\subsubsection{Declaration nodes}
    117124
    118125A declaration node represents either of:
    119126\begin{itemize}
    120127\item
    121 type declaration: @struct@, @union@, @typedef@ or type parameter (see \VRef[Appendix]{s:KindsTypeParameters})
    122 \item
    123 variable declaration
    124 \item
    125 function declaration
     128Type declaration: struct, union, typedef or type parameter (see Appendix A.3)
     129\item
     130Variable declaration
     131\item
     132Function declaration
    126133\end{itemize}
    127134Declarations are introduced by standard C declarations, with the usual scoping rules.
    128 In addition, declarations can also be qualified by the \lstinline[language=CFA]@forall@ clause (which is the origin of \CFA's name):
     135In addition, declarations can also be introduced by the forall clause (which is the origin
     136of \CFA's name):
    129137\begin{cfa}
    130 forall ( <$\emph{TypeParameterList}$> | <$\emph{AssertionList}$> )
     138forall (<$\emph{TypeParameterList}$> | <$\emph{AssertionList}$>)
    131139        $\emph{declaration}$
    132140\end{cfa}
    133 Type parameters in \CFA are similar to \CC template type parameters.
    134 The \CFA declaration
     141Type parameters in \CFA are similar to \CC template type parameters. The \CFA
     142declaration
    135143\begin{cfa}
    136144forall (dtype T) ...
    137145\end{cfa}
    138 behaves similarly to the \CC template declaration
     146behaves similarly as the \CC template declaration
    139147\begin{C++}
    140148template <typename T> ...
    141149\end{C++}
    142150
    143 Assertions are a distinctive feature of \CFA, similar to \emph{interfaces} in D and Go, and \emph{traits} in Rust.
    144 Contrary to the \CC template where arbitrary functions and operators can be used in a template definition, in a \CFA parametric function, operations on parameterized types must be declared in assertions.
     151Assertions are a distinctive feature of \CFA: contrary to the \CC template where
     152arbitrary functions and operators can be used in a template definition, in a \CFA
     153parametric function, operations on parameterized types must be declared in assertions.
     154
    145155Consider the following \CC template:
    146156\begin{C++}
    147 @template@ forall<typename T> T foo( T t ) {
    148         return t + t * t;
     157template <typename T> int foo(T t) {
     158        return bar(t) + baz(t);
    149159}
    150160\end{C++}
    151 where there are no explicit requirements on the type @T@.
    152 Therefore, the \CC compiler must deduce what operators are required during textual (macro) expansion of the template at each usage.
    153 As a result, templates cannot be compiled.
    154 \CFA assertions specify restrictions on type parameters:
     161Unless bar and baz are also parametric functions taking any argument type, they must be
     162declared in the assertions, or otherwise the code will not compile:
    155163\begin{cfa}
    156 forall( dtype T | @{ T ?+?( T, T ); T ?*?( T, T ) }@ ) int foo ( T t ) {
    157         return t + t * t;
     164forall (dtype T | { int bar(T); int baz(t); }) int foo (T t) {
     165        return bar(t) + baz(t);
    158166}
    159167\end{cfa}
    160 Assertions are written using the usual \CFA function declaration syntax.
    161 Only types with operators ``@+@'' and ``@*@'' work with this function, and the function prototype is sufficient to allow separate compilation.
    162 
    163 Type parameters and assertions are used in the following compiler data-structures.
    164 
    165 
    166 \subsubsection{Type Nodes}
    167 
    168 Type nodes represent the type of an object or expression.
    169 Named types reference the corresponding type declarations.
    170 The type of a function is its function pointer type (same as standard C).
    171 With the addition of type parameters, named types may contain a list of parameter values (actual parameter types).
    172 
    173 
    174 \subsubsection{Statement Nodes}
    175 
    176 Statement nodes represent the executable statements in the program, including basic expression statements, control flows and blocks.
     168Assertions are written using the usual function declaration syntax. The scope of type
     169parameters and assertions is the following declaration.
     170
     171\subsubsection{Type nodes}
     172
     173A type node represents the type of an object or expression.
     174Named types reference the corresponding type declarations. The type of a function is its
     175function pointer type (same as standard C).
     176With the addition of type parameters, named types may contain a list of parameter values
     177(actual parameter types).
     178
     179\subsubsection{Statement nodes}
     180
     181Statement nodes represent the statements in the program, including basic expression
     182statements, control flows and blocks.
    177183Local declarations (within a block statement) are represented as declaration statements.
    178184
    179 
    180 \subsubsection{Expression Nodes}
    181 
    182 Some expressions are represented differently before and after the resolution stage:
     185\subsubsection{Expression nodes}
     186
     187Some expressions are represented differently in the compiler before and after resolution
     188stage:
    183189\begin{itemize}
    184190\item
    185 Name expressions: @NameExpr@ pre-resolution, @VariableExpr@ post-resolution
    186 \item
    187 Member expressions: @UntypedMemberExpr@ pre-resolution, @MemberExpr@ post-resolution
    188 \item
    189 \begin{sloppypar}
    190 Function call expressions (including overloadable operators): @UntypedExpr@ pre-resolution, @ApplicationExpr@ post-resolution
    191 \end{sloppypar}
     191Name expressions: NameExpr pre-resolution, VariableExpr post-resolution
     192\item
     193Member expressions: UntypedMemberExpr pre-resolution, MemberExpr post-resolution
     194\item
     195Function call expressions (including overloadable operators): UntypedExpr pre-resolution, ApplicationExpr post-resolution
    192196\end{itemize}
    193 The pre-resolution representation contains only the symbols.
    194 Post-resolution links them to the actual variable and function declarations.
     197The pre-resolution representations contain only the symbols. Post-resolution results link
     198them to the actual variable and function declarations.
    195199
    196200
    197201\subsection{Compilation Passes}
    198202
    199 Compilation steps are implemented as passes, which follows a general structural recursion pattern on the syntax tree.
    200 
    201 The basic workflow of compilation passes follows preorder and postorder traversal on the AST data-structure, implemented with visitor pattern, and can be loosely described with the following pseudocode:
    202 \begin{C++}
    203 Pass::visit( node_t node ) {
    204         previsit( node );
    205         if ( visit_children )
     203Compilation steps are implemented as passes, which follows a general structural recursion
     204pattern on the syntax tree.
     205
     206The basic work flow of compilation passes follows preorder and postorder traversal on
     207tree data structure, implemented with visitor pattern, and can be loosely described with
     208the following pseudocode:
     209\begin{C++}
     210Pass::visit (node_t node) {
     211        previsit(node);
     212        if (visit_children)
    206213                for each child of node:
    207                         child.accept( this );
    208         postvisit( node );
     214                        child.accept(this);
     215        postvisit(node);
    209216}
    210217\end{C++}
    211 Operations in @previsit@ happen in preorder (top to bottom) and operations in @postvisit@ happen in postorder (bottom to top).
    212 The precise order of recursive operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and @AST/Pass.impl.hpp@ (new).
    213 
    214 Implementations of compilation passes follow certain conventions:
     218Operations in previsit() happen in preorder (top to bottom) and operations in
     219postvisit() happen in postorder (bottom to top). The precise order of recursive
     220operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and
     221@AST/Pass.impl.hpp@ (new).
     222Implementations of compilation passes need to follow certain conventions:
    215223\begin{itemize}
    216224\item
    217 Passes \textbf{should not} directly override the visit method (Non-virtual Interface principle);
    218 if a pass desires different recursion behaviour, it should set @visit_children@ to false and perform recursive calls manually within previsit or postvisit procedures.
    219 To enable this option, inherit from the @WithShortCircuiting@ mixin.
    220 \item
    221 previsit may mutate the node but \textbf{must not} change the node type or return @nullptr@.
    222 \item
    223 postvisit may mutate the node, reconstruct it to a different node type, or delete it by returning @nullptr@.
     225Passes \textbf{should not} directly override the visit method (Non-virtual Interface
     226principle); if a pass desires different recursion behavior, it should set
     227@visit_children@ to false and perform recursive calls manually within previsit or
     228postvisit procedures. To enable this option, inherit from @WithShortCircuiting@ mixin.
     229\item
     230previsit may mutate the node but \textbf{must not} change the node type or return null.
     231\item
     232postvisit may mutate the node, reconstruct it to a different node type, or delete it by
     233returning null.
    224234\item
    225235If the previsit or postvisit method is not defined for a node type, the step is skipped.
    226 If the return type is declared as @void@, the original node is returned by default.
    227 These behaviours are controlled by template specialization rules;
    228 see @Common/PassVisitor.proto.h@ (old) and @AST/@ @Pass.proto.hpp@ (new) for details.
     236If the return type is declared as void, the original node is returned by default. These
     237behaviors are controlled by template specialization rules; see
     238@Common/PassVisitor.proto.h@ (old) and @AST/Pass.proto.hpp@ (new) for details.
    229239\end{itemize}
    230240Other useful mixin classes for compilation passes include:
    231241\begin{itemize}
    232242\item
    233 @WithGuards@ allows saving and restoring variable values automatically upon entering/exiting the current node.
    234 \item
    235 @WithVisitorRef@ creates a wrapped entity for the current pass (the actual argument passed to recursive calls internally) for explicit recursion, usually used together with @WithShortCircuiting@.
    236 \item
    237 @WithSymbolTable@ gives a managed symbol table with built-in scoping-rule handling (\eg on entering and exiting a block statement)
     243WithGuards allows saving values of variables and restore automatically upon exiting
     244the current node.
     245\item
     246WithVisitorRef creates a wrapped entity of current pass (the actual argument
     247passed to recursive calls internally) for explicit recursion, usually used together
     248with WithShortCircuiting.
     249\item
     250WithSymbolTable gives a managed symbol table with built-in scoping rule handling
     251(\eg on entering and exiting a block statement)
    238252\end{itemize}
    239 \NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures to its own scope, or otherwise they are not picked up by template resolution:
     253\NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading
     254resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures
     255to its own scope, or otherwise they will not be picked up by template resolution:
    240256\begin{C++}
    241257class Pass2: public Pass1 {
    242         @using Pass1::previsit;@
    243         @using Pass1::postvisit;@
     258        using Pass1::previsit;
     259        using Pass1::postvisit;
    244260        // new procedures
    245261}
     
    247263
    248264
    249 \subsection{Data Structure Change (new-ast)}
    250 
    251 It has been observed that excessive copying of syntax tree structures accounts for a majority of computation cost and significantly slows down the compiler.
    252 In the previous implementation of the syntax tree, every internal node has a unique parent;
    253 therefore all copies are required to duplicate the entire subtree.
    254 A new, experimental re-implementation of the syntax tree (source under directory @AST/@ hereby referred to as ``new-ast'') attempts to overcome this issue with a functional approach that allows sharing of common sub-structures and only makes copies when necessary.
    255 
    256 The core of new-ast is a customized implementation of smart pointers, similar to @std::shared_ptr@ and @std::weak_ptr@ in the \CC standard library.
    257 Reference counting is used to detect sharing and allowing certain optimizations.
    258 For a purely functional (immutable) data-structure, all mutations are modelled by shallow copies along the path of mutation.
     265\subsection{Data Structure Change WIP (new-ast)}
     266
     267It has been observed that excessive copying of syntax tree structures accounts for a
     268majority of computation cost and significantly slows down the compiler. In the previous
     269implementation of the syntax tree, every internal node has a unique parent; therefore all
     270copies are required to duplicate everything down to the bottom. A new, experimental
     271re-implementation of the syntax tree (source under directory AST/ hereby referred to as
     272``new-ast'') attempts to overcome this issue with a functional approach that allows sharing
     273of common sub-structures and only makes copies when necessary.
     274
     275The core of new-ast is a customized implementation of smart pointers, similar to
     276@std::shared_ptr@ and @std::weak_ptr@ in \CC standard library. Reference counting is
     277used to detect sharing and allows optimization. For a purely functional (a.k.a. immutable)
     278data structure, all mutations are modelled by shallow copies along the path of mutation.
    259279With reference counting optimization, unique nodes are allowed to be mutated in place.
    260 This however, may potentially introduce some complications and bugs;
    261 a few issues are discussed near the end of this section.
    262 
    263 
    264 \subsubsection{Source: \lstinline{AST/Node.hpp}}
    265 
    266 Class @ast::Node@ is the base class of all new-ast node classes, which implements reference counting mechanism.
    267 Two different counters are recorded: ``strong'' reference count for number of nodes semantically owning it;
    268 ``weak'' reference count for number of nodes holding a mere reference and only need to observe changes.
    269 Class @ast::ptr_base@ is the smart pointer implementation and also takes care of resource management.
    270 
    271 Direct access through the smart pointer is read-only.
    272 A mutable access should be obtained by calling @shallowCopy@ or mutate as below.
    273 
    274 Currently, the weak pointers are only used to reference declaration nodes from a named type, or a variable expression.
    275 Since declaration nodes are intended to denote unique entities in the program, weak pointers always point to unique (unshared) nodes.
    276 This property may change in the future, and weak references to shared nodes may introduce some problems;
     280This however, may potentially introduce some complications and bugs; a few issues are
     281discussed near the end of this section.
     282
     283\subsubsection{Source: AST/Node.hpp}
     284
     285class @ast::Node@ is the base class of all new-ast node classes, which implements
     286reference counting mechanism. Two different counters are recorded: ``strong'' reference
     287count for number of nodes semantically owning it; ``weak'' reference count for number of
     288nodes holding a mere reference and only need to observe changes.
     289class @ast::ptr_base@ is the smart pointer implementation and also takes care of
     290resource management.
     291
     292Direct access through the smart pointer is read-only. A mutable access should be obtained
     293by calling shallowCopy or mutate as below.
     294
     295Currently, the weak pointers are only used to reference declaration nodes from a named
     296type, or a variable expression. Since declaration nodes are intended to denote unique
     297entities in the program, weak pointers always point to unique (unshared) nodes. This may
     298change in the future, and weak references to shared nodes may introduce some problems;
    277299see mutate function below.
    278300
    279 All node classes should always use smart pointers in structure definitions versus raw pointers.
    280 Function
     301All node classes should always use smart pointers in the structure and should not use raw
     302pointers.
     303
    281304\begin{C++}
    282305void ast::Node::increment(ref_type ref)
    283306\end{C++}
    284 increments this node's strong or weak reference count.
    285 Function
     307Increments this node's strong or weak reference count.
    286308\begin{C++}
    287309void ast::Node::decrement(ref_type ref, bool do_delete = true)
    288310\end{C++}
    289 decrements this node's strong or weak reference count.
    290 If strong reference count reaches zero, the node is deleted.
    291 \NOTE: Setting @do_delete@ to false may result in a detached node.
    292 Subsequent code should manually delete the node or assign it to a strong pointer to prevent memory leak.
    293 
     311Decrements this node's strong or weak reference count. If strong reference count reaches
     312zero, the node is deleted by default.
     313\NOTE: Setting @do_delete@ to false may result in a detached node. Subsequent code should
     314manually delete the node or assign it to a strong pointer to prevent memory leak.
    294315Reference counting functions are internally called by @ast::ptr_base@.
    295 Function
    296316\begin{C++}
    297317template<typename node_t>
    298318node_t * shallowCopy(const node_t * node)
    299319\end{C++}
    300 returns a mutable, shallow copy of node: all child pointers are pointing to the same child nodes.
    301 Function
     320Returns a mutable, shallow copy of node: all child pointers are pointing to the same child
     321nodes.
    302322\begin{C++}
    303323template<typename node_t>
    304324node_t * mutate(const node_t * node)
    305325\end{C++}
    306 returns a mutable pointer to the same node, if the node is unique (strong reference count is 1);
    307 otherwise, it returns @shallowCopy(node)@.
    308 It is an error to mutate a shared node that is weak-referenced.
    309 Currently this does not happen.
    310 A problem may appear once weak pointers to shared nodes (\eg expression nodes) are used;
    311 special care is needed.
    312 
    313 \NOTE: This naive uniqueness check may not be sufficient in some cases.
    314 A discussion of the issue is presented at the end of this section.
    315 Functions
     326If node is unique (strong reference count is 1), returns a mutable pointer to the same node.
     327Otherwise, returns shallowCopy(node).
     328It is an error to mutate a shared node that is weak-referenced. Currently this does not
     329happen. The problem may appear once weak pointers to shared nodes (\eg expression
     330nodes) are used; special care will be needed.
     331
     332\NOTE: This naive uniqueness check may not be sufficient in some cases. A discussion of the
     333issue is presented at the end of this section.
    316334\begin{C++}
    317335template<typename node_t, typename parent_t, typename field_t, typename assn_t>
    318 const node_t * mutate_field(const node_t * node, field_t parent_t::* field, assn_t && val)
     336const node_t * mutate_field(const node_t * node, field_t parent_t::*field, assn_t && val)
    319337\end{C++}
    320338\begin{C++}
     
    324342                field_t && val)
    325343\end{C++}
    326 are helpers for mutating a field on a node using pointer to a member function (creates shallow copy when necessary).
    327 
    328 
    329 \subsubsection{Issue: Undetected Sharing}
    330 
    331 The @mutate@ behaviour described above has a problem: deeper shared nodes may be
     344Helpers for mutating a field on a node using pointer to member (creates shallow copy
     345when necessary).
     346
     347\subsubsection{Issue: Undetected sharing}
     348
     349The @mutate@ behavior described above has a problem: deeper shared nodes may be
    332350mistakenly considered as unique. \VRef[Figure]{f:DeepNodeSharing} shows how the problem could arise:
    333351\begin{figure}
     
    337355\label{f:DeepNodeSharing}
    338356\end{figure}
    339 Given the tree rooted at P1, which is logically the chain P1-A-B, and P2 is irrelevant, assume @mutate(B)@ is called.
    340 The algorithm considers B as unique since it is only directly owned by A.
    341 However, the other tree P2-A-B indirectly shares the node B and is therefore wrongly mutated.
    342 
    343 To partly address this problem, if the mutation is called higher up the tree, a chain mutation helper can be used.
    344 
    345 \subsubsection{Source: \lstinline{AST/Chain.hpp}}
    346 
    347 Function
     357Suppose that we are working on the tree rooted at P1, which
     358is logically the chain P1-A-B and P2 is irrelevant, and then
     359mutate(B) is called. The algorithm considers B as unique since
     360it is only directly owned by A. However, the other tree P2-A-B
     361indirectly shares the node B and is therefore wrongly mutated.
     362
     363To partly address this problem, if the mutation is called higher up the tree, a chain
     364mutation helper can be used:
     365
     366\subsubsection{Source: AST/Chain.hpp}
     367
    348368\begin{C++}
    349369template<typename node_t, Node::ref_type ref_t>
    350370auto chain_mutate(ptr_base<node_t, ref_t> & base)
    351371\end{C++}
    352 returns a chain mutator handle that takes pointer-to-member to go down the tree, while creating shallow copies as necessary;
    353 see @struct _chain_mutator@ in the source code for details.
    354 
    355 For example, in the above diagram, if mutation of B is wanted while at P1, the call using @chain_mutate@ looks like the following:
     372This function returns a chain mutator handle which takes pointer-to-member to go down
     373the tree while creating shallow copies as necessary; see @struct _chain_mutator@ in the
     374source code for details.
     375
     376For example, in the above diagram, if mutation of B is wanted while at P1, the call using
     377@chain_mutate@ looks like the following:
    356378\begin{C++}
    357379chain_mutate(P1.a)(&A.b) = new_value_of_b;
    358380\end{C++}
    359 \NOTE: if some node in chain mutate is shared (therefore shallow copied), it implies that every node further down is also copied, thus correctly executing the functional mutation algorithm.
    360 This example code creates copies of both A and B and performs mutation on the new nodes, so that the other tree P2-A-B is untouched.
    361 However, if a pass traverses down to node B and performs mutation, for example, in @postvisit(B)@, information on sharing higher up is lost.
    362 Since the new-ast structure is only in experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up, this issue does not actually happen.
    363 It should be addressed in the future when other compilation passes are migrated to new-ast and many of them contain procedural mutations, where it might cause accidental mutations to other logically independent trees (\eg common sub-expression) and become a bug.
    364 
    365 
     381Note that if some node in chain mutate is shared (therefore shallow copied), it implies that
     382every node further down will also be copied, thus correctly executing the functional
     383mutation algorithm. This example code creates copies of both A and B and performs
     384mutation on the new nodes, so that the other tree P2-A-B is untouched.
     385However, if a pass traverses down to node B and performs mutation, for example, in
     386@postvisit(B)@, information on sharing higher up is lost. Since the new-ast structure is only in
     387experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up,
     388this issue does not actually happen. It should be addressed in the future when other
     389compilation passes are migrated to new-ast and many of them contain procedural
     390mutations, where it might cause accidental mutations to other logically independent trees
     391(\eg common sub-expression) and become a bug.
     392
     393
     394\vspace*{20pt} % FIX ME, spacing problem with this heading ???
    366395\section{Compiler Algorithm Documentation}
    367396
    368 This compiler algorithm documentation covers most of the resolver, data structures used in variable and expression resolution, and a few directly related passes.
    369 Later passes involving code generation are not included yet;
    370 documentation for those will be done latter.
    371 
     397This documentation currently covers most of the resolver, data structures used in variable
     398and expression resolution, and a few directly related passes. Later passes involving code
     399generation is not included yet; documentation for those will be done afterwards.
    372400
    373401\subsection{Symbol Table}
    374402
    375 \NOTE: For historical reasons, the symbol-table data-structure is called @indexer@ in the old implementation.
    376 Hereby, the name is changed to @SymbolTable@.
    377 The symbol table stores a mapping from names to declarations, implements a similar name-space separation rule, and provides the same scoping rules as standard C.\footnote{ISO/IEC 9899:1999, Sections 6.2.1 and 6.2.3.}
    378 The difference in name-space rule is that @typedef@ aliases are no longer considered ordinary identifiers.
    379 In addition to C tag-types (@struct@, @union@, @enum@), \CFA introduces another tag type, @trait@, which is a named collection of assertions.
    380 
    381 
    382 \subsubsection{Source: \lstinline{AST/SymbolTable.hpp}}
    383 
    384 Function
     403\NOTE: For historical reasons, the symbol table data structure was called ``indexer'' in the
     404old implementation. Hereby we will be using the name SymbolTable everywhere.
     405The symbol table stores a mapping from names to declarations and implements a similar
     406name space separation rule, and the same scoping rules in standard C.\footnote{ISO/IEC 9899:1999, Sections 6.2.1 and 6.2.3} The difference in
     407name space rule is that typedef aliases are no longer considered ordinary identifiers.
     408In addition to C tag types (struct, union, enum), \CFA introduces another tag type, trait,
     409which is a named collection of assertions.
     410
     411\subsubsection{Source: AST/SymbolTable.hpp}
     412
     413\subsubsection{Source: SymTab/Indexer.h}
     414
    385415\begin{C++}
    386416SymbolTable::addId(const DeclWithType * decl)
    387417\end{C++}
    388 provides name mangling of identifiers, since \CFA allows overloading of variables and functions.
    389 The mangling scheme is closely based on the Itanium \CC ABI,\footnote{\url{https://itanium-cxx-abi.github.io/cxx-abi/abi.html}, Section 5.1} while making adaptations to \CFA specific features, mainly assertions and overloaded variables by type.
    390 
    391 Naming conflicts are handled by mangled names;
    392 lookup by name returns a list of declarations with the same identifier name.
    393 Functions
     418Since \CFA allows overloading of variables and functions, ordinary identifier names need
     419to be mangled. The mangling scheme is closely based on the Itanium \CC ABI,\footnote{\url{https://itanium-cxx-abi.github.io/cxx-abi/abi.html}, Section 5.1} while
     420making adaptations to \CFA specific features, mainly assertions and overloaded variables
     421by type. Naming conflicts are handled by mangled names; lookup by name returns a list of
     422declarations with the same literal identifier name.
     423
    394424\begin{C++}
    395425SymbolTable::addStruct(const StructDecl * decl)
     
    398428SymbolTable::addTrait(const TraitDecl * decl)
    399429\end{C++}
    400 add a tag-type declaration to the symbol table.
    401 Function
     430Adds a tag type declaration to the symbol table.
    402431\begin{C++}
    403432SymbolTable::addType(const NamedTypeDecl * decl)
    404433\end{C++}
    405 adds a @typedef@ alias to the symbol table.
    406 
    407 \textbf{C Incompatibility Note}: Since \CFA allows using @struct@, @union@ and @enum@ type-names without a prefix keyword, as in \CC, @typedef@ names and tag-type names cannot be disambiguated by syntax rules.
    408 Currently the compiler puts them together and disallows collision.
    409 The following program is valid C but invalid \CFA (and \CC):
     434Adds a typedef alias to the symbol table.
     435
     436\textbf{C Incompatibility Note}: Since Cforall allows using struct, union and enum type names
     437without the keywords, typedef names and tag type names cannot be disambiguated by
     438syntax rules. Currently the compiler puts them together and disallows collision. The
     439following program is valid C but not valid Cforall:
    410440\begin{C++}
    411441struct A {};
    412 typedef int A; // gcc: ok, cfa: Cannot redefine typedef A
    413 struct A sa; // C disambiguates via struct prefix
    414 A ia;
    415 \end{C++}
    416 In practices, such usage is extremely rare, and hence, this change (as in \CC) has minimal impact on existing C programs.
    417 The declaration
    418 \begin{C++}
    419 struct A {};
    420 typedef struct A A; // A is an alias for struct A
    421 A a;
    422 struct A b;
    423 \end{C++}
    424 is not an error because the alias name is identical to the original.
    425 Finally, the following program is allowed in \CFA:
    426 \begin{C++}
    427442typedef int A;
    428 void A(); // name mangled
     443// gcc: ok, cfa: Cannot redefine typedef A
     444\end{C++}
     445In actual practices however, such usage is extremely rare, and typedef struct A A; is
     446not considered an error, but silently discarded. Therefore, we expect this change to have
     447minimal impact on existing C programs.
     448Meanwhile, the following program is allowed in Cforall:
     449\begin{C++}
     450typedef int A;
     451void A();
    429452// gcc: A redeclared as different kind of symbol, cfa: ok
    430453\end{C++}
    431 because the function name is mangled.
    432 
    433454
    434455\subsection{Type Environment and Unification}
    435456
    436 The following core ideas underlie the parametric type-resolution algorithm.
    437 A type environment organizes type parameters into \textbf{equivalent classes} and maps them to actual types.
    438 Unification is the algorithm that takes two (possibly parametric) types and parameter mappings, and attempts to produce a common type by matching information in the type environments.
     457The core of parametric type resolution algorithm.
     458Type Environment organizes type parameters in \textbf{equivalent classes} and maps them to
     459actual types. Unification is the algorithm that takes two (possibly parametric) types and
     460parameter mappings and attempts to produce a common type by matching the type
     461environments.
    439462
    440463The unification algorithm is recursive in nature and runs in two different modes internally:
    441464\begin{itemize}
    442465\item
    443 Exact unification mode requires equivalent parameters to match perfectly.
    444 \item
    445 Inexact unification mode allows equivalent parameters to be converted to a common type.
     466\textbf{Exact} unification mode requires equivalent parameters to match perfectly;
     467\item
     468\textbf{Inexact} unification mode allows equivalent parameters to be converted to a
     469common type.
    446470\end{itemize}
    447 For a pair of matching parameters (actually, their equivalent classes), if either side is open (not bound to a concrete type yet), they are combined.
    448 
    449 Within the inexact mode, types are allowed to differ on their cv-qualifiers (\eg @const@, @volatile@, \etc);
    450 additionally, if a type never appear either in a parameter list or as the base type of a pointer, it may also be widened (\ie safely converted).
    451 As \CFA currently does not implement subclassing as in object-oriented languages, widening conversions are only on the primitive types, \eg conversion from @int@ to @long int@.
    452 
    453 The need for two unification modes comes from the fact that parametric types are considered compatible only if all parameters are exactly the same (not just compatible).
    454 Pointer types also behaves similarly;
    455 in fact, they may be viewed as a primitive kind of parametric types.
    456 @int *@ and @long *@ are different types, just like @vector(int)@ and @vector(long)@ are, for the parametric type @*(T)@ / @vector(T)@, respectively.
    457 
    458 The resolver uses the following @public@ functions:\footnote{
    459 Actual code also tracks assertions on type parameters; those extra arguments are omitted here for conciseness.}
    460 
    461 
    462 \subsubsection{Source: \lstinline{ResolvExpr/Unify.cc}}
    463 
    464 Function
    465 \begin{C++}
    466 bool unify(const Type * type1, const Type * type2, TypeEnvironment & env,
    467         OpenVarSet & openVars, const SymbolTable & symtab, Type *& commonType)
    468 \end{C++}
    469 returns a boolean indicating if the unification succeeds or fails after attempting to unify @type1@ and @type2@ within current type environment.
    470 If the unify succeeds, @env@ is modified by combining the equivalence classes of matching parameters in @type1@ and @type2@, and their common type is written to @commonType@.
    471 If the unify fails, nothing changes.
    472 Functions
    473 \begin{C++}
    474 bool typesCompatible(const Type * type1, const Type * type2, const SymbolTable & symtab,
    475         const TypeEnvironment & env)
    476 bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type * type2,
    477         const SymbolTable & symtab, const TypeEnvironment & env)
    478 \end{C++}
    479 return a boolean indicating if types @type1@ and @type2@ can possibly be the same type.
    480 The second version ignores the outermost cv-qualifiers if present.\footnote{
    481 In \lstinline@const int * const@, only the second \lstinline@const@ is ignored.}
    482 These function have no side effects.
    483 
    484 \NOTE: No attempt is made to widen the types (exact unification is used), although the function names may suggest otherwise, \eg @typesCompatible(int, long)@ returns false.
     471For a pair of matching parameters (actually, their equivalent classes), if either side is open
     472(not bound to a concrete type yet), they are simply combined.
     473
     474Within inexact mode, types are allowed to differ on their cv-qualifiers; additionally, if a
     475type never appear either in parameter list or as the base type of a pointer, it may also be
     476widened (i.e. safely converted). As Cforall currently does not implement subclassing similar
     477to object-oriented languages, widening conversions are on primitive types only, for
     478example the conversion from int to long.
     479
     480The need for two unification modes come from the fact that parametric types are
     481considered compatible only if all parameters are exactly the same (not just compatible).
     482Pointer types also behaves similarly; in fact, they may be viewed as a primitive kind of
     483parametric types. @int*@ and @long*@ are different types, just like @vector(int)@ and
     484@vector(long)@ are, for the parametric type @vector(T)@.
     485
     486The resolver should use the following ``@public@'' functions:\footnote{
     487Actual code also tracks assertions on type parameters; those extra arguments are omitted here for
     488conciseness.}
     489
     490
     491\subsubsection{Source: ResolvExpr/Unify.cc}
     492
     493\begin{C++}
     494bool unify(const Type *type1, const Type *type2, TypeEnvironment &env,
     495OpenVarSet &openVars, const SymbolTable &symtab, Type *&commonType)
     496\end{C++}
     497Attempts to unify @type1@ and @type2@ with current type environment.
     498
     499If operation succeeds, @env@ is modified by combining the equivalence classes of matching
     500parameters in @type1@ and @type2@, and their common type is written to commonType.
     501
     502If operation fails, returns false.
     503\begin{C++}
     504bool typesCompatible(const Type * type1, const Type * type2, const
     505SymbolTable &symtab, const TypeEnvironment &env)
     506bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type *
     507type2, const SymbolTable &symtab, const TypeEnvironment &env)
     508\end{C++}
     509
     510Determines if type1 and type2 can possibly be the same type. The second version ignores
     511the outermost cv-qualifiers if present.\footnote{
     512In const \lstinline@int * const@, only the second \lstinline@const@ is ignored.}
     513
     514The call has no side effect.
     515
     516\NOTE: No attempts are made to widen the types (exact unification is used), although the
     517function names may suggest otherwise. E.g. @typesCompatible(int, long)@ returns false.
    485518
    486519
    487520\subsection{Expression Resolution}
    488521
    489 The design of the current version of expression resolver is outlined in the Ph.D.\ thesis by Aaron Moss~\cite{Moss19}.
     522The design of the current version of expression resolver is outlined in the Ph.D. Thesis from
     523Aaron Moss~\cite{Moss19}.
     524
    490525A summary of the resolver algorithm for each expression type is presented below.
    491526
    492 All overloadable operators are modelled as function calls.
    493 For a function call, interpretations of the function and arguments are found recursively.
    494 Then the following steps produce a filtered list of valid interpretations:
     527All overloadable operators are modelled as function calls. For a function call,
     528interpretations of the function and arguments are found recursively. Then the following
     529steps produce a filtered list of valid interpretations:
    495530\begin{enumerate}
    496531\item
    497 From all possible combinations of interpretations of the function and arguments, those where argument types may be converted to function parameter types are considered valid.
     532From all possible combinations of interpretations of the function and arguments,
     533those where argument types may be converted to function parameter types are
     534considered valid.
    498535\item
    499536Valid interpretations with the minimum sum of argument costs are kept.
    500537\item
    501 \label{p:argcost}
    502 Argument costs are then discarded; the actual cost for the function call expression is the sum of conversion costs from the argument types to parameter types.
    503 \item
    504 \label{p:returntype}
    505 For each return type, the interpretations with satisfiable assertions are then sorted by actual cost computed in step~\ref{p:argcost}.
    506 If for a given type, the minimum cost interpretations are not unique, that return type is ambiguous.
    507 If the minimum cost interpretation is unique but contains an ambiguous argument, it is also ambiguous.
     538Argument costs are then discarded; the actual cost for the function call expression is
     539the sum of conversion costs from the argument types to parameter types.
     540\item
     541For each return type, the interpretations with satisfiable assertions are then sorted
     542by actual cost computed in step 3. If for a given type, the minimum cost
     543interpretations are not unique, it is said that for that return type the interpretation
     544is ambiguous. If the minimum cost interpretation is unique but contains an
     545ambiguous argument, it is also considered ambiguous.
    508546\end{enumerate}
    509 Therefore, for each return type, the resolver produces:
     547Therefore, for each return type, the resolver produces either of:
    510548\begin{itemize}
    511549\item
    512 no alternatives
    513 \item
    514 a single valid alternative
    515 \item
    516 an ambiguous alternative
     550No alternatives
     551\item
     552A single valid alternative
     553\item
     554An ambiguous alternative
    517555\end{itemize}
    518 \NOTE: an ambiguous alternative may be discarded at the parent expressions because a different return type matches better for the parent expressions.
    519 
    520 The \emph{non}-overloadable expressions in \CFA are: cast expressions, address-of (unary @&@) expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional expression (@?:@).
    521 
    522 For a cast expression, the convertible argument types are kept.
    523 Then the result is selected by lowest argument cost, and further by lowest conversion cost to target type.
    524 If the lowest cost is still not unique or an ambiguous argument interpretation is selected, the cast expression is ambiguous.
    525 In an expression statement, the top level expression is implicitly cast to @void@.
     556Note that an ambiguous alternative may be discarded at the parent expressions because a
     557different return type matches better for the parent expressions.
     558
     559The non-overloadable expressions in Cforall are: cast expressions, address-of (unary @&@)
     560expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional
     561expression (@?:@).
     562
     563For a cast expression, the convertible argument types are kept. Then the result is selected
     564by lowest argument cost, and further by lowest conversion cost to target type. If the lowest
     565cost is still not unique, or an ambiguous argument interpretation is selected, the cast
     566expression is ambiguous. In an expression statement, the top level expression is implicitly
     567cast to void.
    526568
    527569For an address-of expression, only lvalue results are kept and the minimum cost is selected.
    528570
    529 For logical expressions @&&@ and @||@, arguments are implicitly cast to @bool@, and follow the rules fr cast expression above.
    530 
    531 For the ternary conditional expression, the condition is implicitly cast to @bool@, and the branch expressions must have compatible types.
    532 Each pair of compatible branch expression types produce a possible interpretation, and the cost is defined as the sum of the expression costs plus the sum of conversion costs to the common type.
    533 
    534 
    535 \subsection{Conversion and Application Cost}
    536 
    537 There were some unclear parts in the previous documentation in the cost system, as described in the Moss thesis~\cite{Moss19}, section 4.1.2.
    538 Some clarification are presented in this section.
    539 
    540 \begin{enumerate}
    541 \item
    542 Conversion to a type denoted by parameter may incur additional cost if the match is not exact.
    543 For example, if a function is declared to accept @(T, T)@ and receives @(int, long)@, @T@ is deducted @long@ and an additional widening conversion cost is added for @int@ to @T@.
    544 
    545 \item
    546 The specialization level of a function is the sum of the least depth of an appearance of a type parameter (counting pointers, references and parameterized types), plus the number of assertions.
    547 A higher specialization level is favoured if argument conversion costs are equal.
    548 
    549 \item
    550 Coercion of pointer types is only allowed in explicit cast expressions;
    551 the only allowed implicit pointer casts are adding qualifiers to the base type and cast to @void*@, and these counts as safe conversions.
    552 Note that implicit cast from @void *@ to other pointer types is no longer valid, as opposed to standard C.
    553 \end{enumerate}
     571For logical expressions @&&@ and @||@, arguments are implicitly cast to bool, and follow the rule
     572of cast expression as above.
     573
     574For the ternary conditional expression, the condition is implicitly cast to bool, and the
     575branch expressions must have compatible types. Each pair of compatible branch
     576expression types produce a possible interpretation, and the cost is defined as the sum of
     577expression costs plus the sum of conversion costs to the common type.
     578
     579TODO: Write a specification for expression costs.
    554580
    555581
    556582\subsection{Assertion Satisfaction}
    557583
    558 The resolver tries to satisfy assertions on expressions only when it is needed: either while selecting from multiple alternatives of a same result type for a function call (step \ref{p:returntype} of resolving function calls) or upon reaching the top level of an expression statement.
    559 
    560 Unsatisfiable alternatives are discarded.
    561 Satisfiable alternatives receive \textbf{implicit parameters}: in \CFA, parametric functions may be separately compiled, as opposed to \CC templates which are only compiled at instantiation.
    562 Given the parametric function-definition:
     584The resolver tries to satisfy assertions on expressions only when it is needed: either while
     585selecting from multiple alternatives of a same result type for a function call (step 4 of
     586resolving function calls), or upon reaching the top level of an expression statement.
     587
     588Unsatisfiable alternatives are discarded. Satisfiable alternatives receive \textbf{implicit
     589parameters}: in Cforall, parametric functions are designed such that they can be compiled
     590separately, as opposed to \CC templates which are only compiled at instantiation. Given a
     591parametric function definition:
    563592\begin{C++}
    564593forall (otype T | {void foo(T);})
    565594void bar (T t) { foo(t); }
    566595\end{C++}
    567 the function @bar@ does not know which @foo@ to call when compiled without knowing the call site, so it requests a function pointer to be passed as an extra argument.
    568 At the call site, implicit parameters are automatically inserted by the compiler.
    569 
    570 Implementation of implicit parameters is discussed in \VRef[Appendix]{s:ImplementationParametricFunctions}.
     596The function bar does not know which @foo@ to call when compiled without knowing the call
     597site, so it requests a function pointer to be passed as an extra argument. At the call site,
     598implicit parameters are automatically inserted by the compiler.
     599
     600\textbf{TODO}: Explain how recursive assertion satisfaction and polymorphic recursion work.
     601
    571602
    572603\section{Tests}
     
    574605\subsection{Test Suites}
    575606
    576 Automatic test suites are located under the @tests/@ directory.
    577 A test case consists of an input CFA source file (suffix @.cfa@), and an expected output file located in the @tests/.expect/@ directory, with the same file name ending with suffix @.txt@.
    578 For example, the test named @tests/tuple/tupleCast.cfa@ has the following files, for example:
     607Automatic test suites are located under the @tests/@ directory. A test case consists of an
     608input CFA source file (name ending with @.cfa@), and an expected output file located
     609in @.expect/@ directory relative to the source file, with the same file name ending with @.txt@.
     610So a test named @tuple/tupleCast@ has the following files, for example:
    579611\begin{C++}
    580612tests/
    581         tuple/
    582                 .expect/
    583                         tupleCast.txt
    584                 tupleCast.cfa
    585 \end{C++}
    586 If compilation fails, the error output is compared to the expect file.
    587 If the compilation succeeds but does not generate an executable, the compilation output is compared to the expect file.
    588 If the compilation succeeds and generates an executable, the executable is run and its output is compared to the expect file.
    589 To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of test names to be run, or @--all@ (or @make all-tests@) to run all tests.
    590 The test script reports test cases fail/success, compilation time and program run time.
    591 To see all the options available for @test.py@ using the @--help@ option.
     613..     tuple/
     614......     .expect/
     615..........       tupleCast.txt
     616......     tupleCast.cfa
     617\end{C++}
     618If compilation fails, the error output is compared to the expect file. If compilation succeeds,
     619the built program is run and its output compared to the expect file.
     620To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of
     621test names to be run, or @--all@ to run all tests. The test script reports test cases
     622fail/success, compilation time and program run time.
    592623
    593624
    594625\subsection{Performance Reports}
    595626
    596 To turn on performance reports, pass the @-XCFA -S@ flag to the compiler.
    597 Three kinds of performance reports are available:
     627To turn on performance reports, pass @-S@ flag to the compiler.
     628
     6293 kinds of performance reports are available:
    598630\begin{enumerate}
    599631\item
     
    607639@Common/Stats/Counter.h@.
    608640\end{enumerate}
    609 It is suggested to run performance tests with optimization (@g++@ flag @-O3@).
    610 
    611 
    612 \appendix
    613 \section{Appendix}
    614 
    615 \subsection{Kinds of Type Parameters}
    616 \label{s:KindsTypeParameters}
    617 
    618 A type parameter in a @forall@ clause has 3 kinds:
    619 \begin{enumerate}[listparindent=0pt]
    620 \item
    621 @dtype@: any data type (built-in or user defined) that is not a concrete type.
    622 
    623 A non-concrete type is an incomplete type such as an opaque type or pointer/reference with an implicit (pointer) size and implicitly generated reference and dereference operations.
    624 \item
    625 @otype@: any data type (built-in or user defined) that is concrete type.
    626 
    627 A concrete type is a complete type, \ie types that can be used to create a variable, which also implicitly asserts the existence of default and copy constructors, assignment, and destructor\footnote{\CFA implements the same automatic resource management (RAII) semantics as \CC.}.
    628 % \item
    629 % @ftype@: any function type.
    630 %
    631 % @ftype@ provides two purposes:
    632 % \begin{itemize}
    633 % \item
    634 % Differentiate function pointer from data pointer because (in theory) some systems have different sizes for these pointers.
    635 % \item
    636 % Disallow a function pointer to match an overloaded data pointer, since variables and functions can have the same names.
    637 % \end{itemize}
    638 
    639 \item
    640 @ttype@: tuple (variadic) type.
    641 
    642 Restricted to the type for the last parameter in a function, it provides a type-safe way to implement variadic functions.
    643 Note however, that it has certain restrictions, as described in the implementation section below.
    644 \end{enumerate}
    645 
    646 
    647 \subsection{GNU C Nested Functions}
    648 
    649 \CFA is designed to be mostly compatible with GNU C, an extension to ISO C99 and C11 standards. The \CFA compiler also implements some language features by GCC extensions, most notably nested functions.
    650 
    651 In ISO C, function definitions are not allowed to be nested. GCC allows nested functions with full lexical scoping. The following example is taken from GCC documentation\footnote{\url{https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html}}:
    652 \begin{C++}
    653 void bar( int * array, int offset, int size ) {
    654         int access( int * array, int index ) { return array[index + offset]; }
    655         int i;
    656         /* ... */
    657         for ( i = 0; i < size; i++ )
    658                 /* ... */ access (array, i) /* ... */
    659 }
    660 \end{C++}
    661 GCC nested functions behave identically to \CC lambda functions with default by-reference capture (stack-allocated, lifetime ends upon exiting the declared block), while also possible to be passed as arguments with standard function pointer types.
    662 
    663 
    664 \subsection{Implementation of Parametric Functions}
    665 \label{s:ImplementationParametricFunctions}
    666 
    667 \CFA implements parametric functions using the implicit parameter approach: required assertions are passed to the callee by function pointers;
    668 size of a parametric type must also be known if referenced directly (\ie not as a pointer).
    669 
    670 The implementation is similar to the one from Scala\footnote{\url{https://www.scala-lang.org/files/archive/spec/2.13/07-implicits.html}}, with some notable differences in resolution:
    671 \begin{enumerate}
    672 \item
    673 All types, variables, and functions are candidates of implicit parameters
    674 \item
    675 The parameter (assertion) name must match the actual declarations.
    676 \end{enumerate}
    677 
    678 For example, the \CFA function declaration
    679 \begin{cfa}
    680 forall( otype T | { int foo( T, int ); } )
    681 int bar(T);
    682 \end{cfa}
    683 after implicit parameter expansion, has the actual signature\footnote{\textbf{otype} also requires the type to have constructor and destructor, which are the first two function pointers preceding the one for \textbf{foo}.}
    684 \begin{C++}
    685 int bar( T, size_t, void (*)(T&), void (*)(T&), int (*)(T, int) );
    686 \end{C++}
    687 The implicit parameter approach has an apparent issue: when the satisfying declaration is also parametric, it may require its own implicit parameters too.
    688 That also causes the supplied implicit parameter to have a different \textbf{actual} type than the \textbf{nominal} type, so it cannot be passed directly.
    689 Therefore, a wrapper with matching actual type must be created, and it is here where GCC nested functions are used internally by the compiler.
    690 
    691 Consider the following program:
    692 \begin{cfa}
    693 int assertion(int);
    694 
    695 forall( otype T | { int assertion(T); } )
    696 void foo(T);
    697 
    698 forall(otype T | { void foo(T); } )
    699 void bar(T t) {
    700         foo(t);
    701 }
    702 \end{cfa}
    703 The \CFA compiler translates the program to non-parametric form\footnote{In the final code output, \lstinline@T@ needs to be replaced by an opaque type, and arguments must be accessed by a frame pointer offset table, due to the unknown sizes. The presented code here is simplified for better understanding.}
    704 \begin{C++}
    705 // ctor, dtor and size arguments are omitted
    706 void foo(T, int (*)(T));
    707 
    708 void bar(T t, void (*foo)(T)) {
    709         foo(t);
    710 }
    711 \end{C++}
    712 However, when @bar(1)@ is called, @foo@ cannot be directly provided as an argument:
    713 \begin{C++}
    714 bar(1, foo); // WRONG: foo has different actual type
    715 \end{C++}
    716 and an additional step is required:
    717 \begin{C++}
    718 {
    719         void _foo_wrapper(int t) {
    720                 foo( t, assertion );
    721         }
    722         bar( 1, _foo_wrapper );
    723 }
    724 \end{C++}
    725 Nested assertions and implicit parameter creation may continue indefinitely.
    726 This issue is a limitation of implicit parameter implementation.
    727 In particular, polymorphic variadic recursion must be structural (\ie the number of arguments decreases in any possible recursive calls), otherwise code generation gets into an infinite loop.
    728 The \CFA compiler sets a limit on assertion depth and reports an error if assertion resolution does not terminate within the limit (as for \lstinline[language=C++]@templates@ in \CC).
     641It is suggested to run performance tests with optimized build (@g++@ flag @-O3@)
     642
    729643
    730644\bibliographystyle{plain}
  • doc/user/Makefile

    r223a633 r33c3ded  
    5555
    5656${DOCUMENT} : ${BASE}.ps
    57         ps2pdf -dPDFSETTINGS=/prepress $<
     57        ps2pdf $<
    5858
    5959${BASE}.ps : ${BASE}.dvi
  • doc/user/user.tex

    r223a633 r33c3ded  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Mon Oct  5 08:57:29 2020
    14 %% Update Count     : 3998
     13%% Last Modified On : Fri Mar  6 13:34:52 2020
     14%% Update Count     : 3924
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
     32\usepackage{xspace}
    3233\usepackage{varioref}                                                                   % extended references
    33 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig}
    34 \renewcommand{\thesubfigure}{\alph{subfigure})}
     34\usepackage{listings}                                                                   % format program code
    3535\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3636\usepackage{latexsym}                                   % \Box glyph
    3737\usepackage{mathptmx}                                   % better math font with "times"
    3838\usepackage[usenames]{color}
    39 \newcommand{\CFALatin}{}
     39\input{common}                                          % common CFA document macros
     40\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
     41\usepackage{breakurl}
     42
     43\usepackage[pagewise]{lineno}
     44\renewcommand{\linenumberfont}{\scriptsize\sffamily}
     45\usepackage[firstpage]{draftwatermark}
     46\SetWatermarkLightness{0.9}
     47
     48% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
     49% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     50% AFTER HYPERREF.
     51\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     52
     53\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     54\setlength{\headsep}{0.25in}
     55
     56%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     57
     58\CFAStyle                                                                                               % use default CFA format-style
     59\lstnewenvironment{C++}[1][]                            % use C++ style
     60{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
     61{}
     62
    4063% inline code ©...© (copyright symbol) emacs: C-q M-)
    4164% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    4568% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    4669% math escape $...$ (dollar symbol)
    47 \input{common}                                          % common CFA document macros
    48 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    49 \usepackage{breakurl}
    50 
    51 \renewcommand\footnoterule{\kern -3pt\rule{0.3\linewidth}{0.15pt}\kern 2pt}
    52 
    53 \usepackage[pagewise]{lineno}
    54 \renewcommand{\linenumberfont}{\scriptsize\sffamily}
    55 \usepackage[firstpage]{draftwatermark}
    56 \SetWatermarkLightness{0.9}
    57 
    58 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    59 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
    60 % AFTER HYPERREF.
    61 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    62 
    63 \setlength{\topmargin}{-0.45in}                                                 % move running title into header
    64 \setlength{\headsep}{0.25in}
    65 
    66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    67 
    68 \CFAStyle                                                                                               % use default CFA format-style
    69 \lstnewenvironment{C++}[1][]                            % use C++ style
    70 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
    71 {}
    72 
    73 \newsavebox{\myboxA}
    74 \newsavebox{\myboxB}
    7570
    7671%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    8479\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    8580\newcommand{\KWC}{K-W C\xspace}
     81
     82\newsavebox{\LstBox}
    8683
    8784%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    256253
    257254The signature feature of \CFA is \emph{\Index{overload}able} \Index{parametric-polymorphic} functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a ©forall© clause (giving the language its name):
    258 \begin{cfa}
     255\begin{lstlisting}
    259256®forall( otype T )® T identity( T val ) { return val; }
    260257int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
    261 \end{cfa}
     258\end{lstlisting}
    262259% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
    263260\CFA{}\hspace{1pt}'s polymorphism was originally formalized by \Index*{Glen Ditchfield}\index{Ditchfield, Glen}~\cite{Ditchfield92}, and first implemented by \Index*{Richard Bilson}\index{Bilson, Richard}~\cite{Bilson03}.
     
    278275\begin{comment}
    279276A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array:
    280 \begin{cfa}
     277\begin{lstlisting}
    281278void * bsearch( const void * key, const void * base, size_t dim, size_t size,
    282279                                int (* compar)( const void *, const void * ));
     
    287284double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    288285double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
    289 \end{cfa}
     286\end{lstlisting}
    290287which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
    291 \begin{cfa}
     288\begin{lstlisting}
    292289forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
    293290        int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ }
     
    300297double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
    301298int posn = bsearch( 5.0, vals, 10 );
    302 \end{cfa}
     299\end{lstlisting}
    303300The nested function ©comp© provides the hidden interface from typed \CFA to untyped (©void *©) C, plus the cast of the result.
    304301Providing a hidden ©comp© function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
     
    308305\CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations.
    309306For example, it is possible to write a type-safe \CFA wrapper ©malloc© based on the C ©malloc©:
    310 \begin{cfa}
     307\begin{lstlisting}
    311308forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    312309int * ip = malloc(); §\C{// select type and size from left-hand side}§
    313310double * dp = malloc();
    314311struct S {...} * sp = malloc();
    315 \end{cfa}
     312\end{lstlisting}
    316313where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    317314\end{comment}
     
    946943the same level as a ©case© clause; the target label may be case ©default©, but only associated
    947944with the current ©switch©/©choose© statement.
     945
     946
     947\subsection{Loop Control}
     948
     949The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
     950\begin{itemize}
     951\item
     952The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.
     953\item
     954An empty conditional implies comparison value of ©1© (true).
     955\item
     956A comparison N is implicit up-to exclusive range [0,N©®)®©.
     957\item
     958A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
     959\item
     960The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
     961\item
     962The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
     963\item
     964The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
     965\item
     966The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.
     967\item
     968©0© is the implicit start value;
     969\item
     970©1© is the implicit increment value.
     971\item
     972The up-to range uses operator ©+=© for increment;
     973\item
     974The down-to range uses operator ©-=© for decrement.
     975\item
     976©@© means put nothing in this field.
     977\item
     978©:© means start another index.
     979\end{itemize}
    948980
    949981\begin{figure}
     
    10541086
    10551087
    1056 \subsection{Loop Control}
    1057 
    1058 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
    1059 \begin{itemize}
    1060 \item
    1061 The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.
    1062 \item
    1063 An empty conditional implies comparison value of ©1© (true).
    1064 \item
    1065 A comparison N is implicit up-to exclusive range [0,N©®)®©.
    1066 \item
    1067 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
    1068 \item
    1069 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
    1070 \item
    1071 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
    1072 \item
    1073 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
    1074 \item
    1075 The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.
    1076 \item
    1077 ©0© is the implicit start value;
    1078 \item
    1079 ©1© is the implicit increment value.
    1080 \item
    1081 The up-to range uses operator ©+=© for increment;
    1082 \item
    1083 The down-to range uses operator ©-=© for decrement.
    1084 \item
    1085 ©@© means put nothing in this field.
    1086 \item
    1087 ©:© means start another index.
    1088 \end{itemize}
    1089 
    1090 
    10911088%\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}}
    10921089\subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}}
     
    10981095for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
    10991096\VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels.
    1100 The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
     1097The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
    11011098
    11021099\begin{figure}
    1103 \centering
    1104 \begin{lrbox}{\myboxA}
    1105 \begin{cfa}[tabsize=3]
    1106 ®Compound:® {
    1107         ®Try:® try {
    1108                 ®For:® for ( ... ) {
    1109                         ®While:® while ( ... ) {
    1110                                 ®Do:® do {
    1111                                         ®If:® if ( ... ) {
    1112                                                 ®Switch:® switch ( ... ) {
    1113                                                         case 3:
    1114                                                                 ®break Compound®;
    1115                                                                 ®break Try®;
    1116                                                                 ®break For®;      /* or */  ®continue For®;
    1117                                                                 ®break While®;  /* or */  ®continue While®;
    1118                                                                 ®break Do®;      /* or */  ®continue Do®;
    1119                                                                 ®break If®;
    1120                                                                 ®break Switch®;
    1121                                                         } // switch
    1122                                                 } else {
    1123                                                         ... ®break If®; ...     // terminate if
    1124                                                 } // if
    1125                                 } while ( ... ); // do
    1126                         } // while
    1127                 } // for
    1128         } ®finally® { // always executed
    1129         } // try
     1100\begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     1101\multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}   & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
     1102\begin{cfa}
     1103®LC:® {
     1104        ... §declarations§ ...
     1105        ®LS:® switch ( ... ) {
     1106          case 3:
     1107                ®LIF:® if ( ... ) {
     1108                        ®LF:® for ( ... ) {
     1109                                ®LW:® while ( ... ) {
     1110                                        ... break ®LC®; ...
     1111                                        ... break ®LS®; ...
     1112                                        ... break ®LIF®; ...
     1113                                        ... continue ®LF;® ...
     1114                                        ... break ®LF®; ...
     1115                                        ... continue ®LW®; ...
     1116                                        ... break ®LW®; ...
     1117                                } // while
     1118                        } // for
     1119                } else {
     1120                        ... break ®LIF®; ...
     1121                } // if
     1122        } // switch
    11301123} // compound
    11311124\end{cfa}
    1132 \end{lrbox}
    1133 
    1134 \begin{lrbox}{\myboxB}
    1135 \begin{cfa}[tabsize=3]
     1125&
     1126\begin{cfa}
    11361127{
    1137 
    1138                 ®ForC:® for ( ... ) {
    1139                         ®WhileC:® while ( ... ) {
    1140                                 ®DoC:® do {
    1141                                         if ( ... ) {
    1142                                                 switch ( ... ) {
    1143                                                         case 3:
    1144                                                                 ®goto Compound®;
    1145                                                                 ®goto Try®;
    1146                                                                 ®goto ForB®;      /* or */  ®goto ForC®;
    1147                                                                 ®goto WhileB®;  /* or */  ®goto WhileC®;
    1148                                                                 ®goto DoB®;      /* or */  ®goto DoC®;
    1149                                                                 ®goto If®;
    1150                                                                 ®goto Switch®;
    1151                                                         } ®Switch:® ;
    1152                                                 } else {
    1153                                                         ... ®goto If®; ...      // terminate if
    1154                                                 } ®If:®;
    1155                                 } while ( ... ); ®DoB:® ;
    1156                         } ®WhileB:® ;
    1157                 } ®ForB:® ;
    1158 
    1159 
    1160 } ®Compound:® ;
    1161 \end{cfa}
    1162 \end{lrbox}
    1163 
    1164 \subfloat[\CFA]{\label{f:CFibonacci}\usebox\myboxA}
    1165 \hspace{2pt}
    1166 \vrule
    1167 \hspace{2pt}
    1168 \subfloat[C]{\label{f:CFAFibonacciGen}\usebox\myboxB}
     1128        ... §declarations§ ...
     1129        switch ( ... ) {
     1130          case 3:
     1131                if ( ... ) {
     1132                        for ( ... ) {
     1133                                while ( ... ) {
     1134                                        ... goto ®LC®; ...
     1135                                        ... goto ®LS®; ...
     1136                                        ... goto ®LIF®; ...
     1137                                        ... goto ®LFC®; ...
     1138                                        ... goto ®LFB®; ...
     1139                                        ... goto ®LWC®; ...
     1140                                        ... goto ®LWB®; ...
     1141                                  ®LWC®: ; } ®LWB:® ;
     1142                          ®LFC:® ; } ®LFB:® ;
     1143                } else {
     1144                        ... goto ®LIF®; ...
     1145                } ®L3:® ;
     1146        } ®LS:® ;
     1147} ®LC:® ;
     1148\end{cfa}
     1149&
     1150\begin{cfa}
     1151
     1152
     1153
     1154
     1155
     1156
     1157
     1158// terminate compound
     1159// terminate switch
     1160// terminate if
     1161// continue loop
     1162// terminate loop
     1163// continue loop
     1164// terminate loop
     1165
     1166
     1167
     1168// terminate if
     1169
     1170
     1171
     1172\end{cfa}
     1173\end{tabular}
    11691174\caption{Multi-level Exit}
    11701175\label{f:MultiLevelExit}
     
    14211426try {
    14221427        f(...);
    1423 } catch( E e ; §boolean-predicate§ ) {          §\C{// termination handler}§
     1428} catch( E e ; §boolean-predicate§ ) {          §\C[8cm]{// termination handler}§
    14241429        // recover and continue
    1425 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§
     1430} catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§
    14261431        // repair and return
    14271432} finally {
     
    34863491For implicit formatted input, the common case is reading a sequence of values separated by whitespace, where the type of an input constant must match with the type of the input variable.
    34873492\begin{cquote}
    3488 \begin{lrbox}{\myboxA}
     3493\begin{lrbox}{\LstBox}
    34893494\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    34903495int x;   double y   char z;
     
    34923497\end{lrbox}
    34933498\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}}
    3494 \multicolumn{1}{@{}l@{}}{\usebox\myboxA} \\
     3499\multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\
    34953500\multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}}       & \multicolumn{1}{c}{\textbf{Python}}   \\
    34963501\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     
    66676672For example, an initial alignment and fill capability are preserved during a resize copy so the copy has the same alignment and extended storage is filled.
    66686673Without sticky properties it is dangerous to use ©realloc©, resulting in an idiom of manually performing the reallocation to maintain correctness.
    6669 \begin{cfa}
    6670 
    6671 \end{cfa}
    66726674
    66736675\CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in
     
    67196721
    67206722        // §\CFA§ safe general allocation, fill, resize, alignment, array
    6721         T * alloc( void );§\indexc{alloc}§                                      §\C[3.5in]{// variable, T size}§
    6722         T * alloc( size_t dim );                                                        §\C{// array[dim], T size elements}§
    6723         T * alloc( T ptr[], size_t dim );                                       §\C{// realloc array[dim], T size elements}§
    6724 
    6725         T * alloc_set( char fill );§\indexc{alloc_set}§         §\C{// variable, T size, fill bytes with value}§
    6726         T * alloc_set( T fill );                                                        §\C{// variable, T size, fill with value}§
    6727         T * alloc_set( size_t dim, char fill );                         §\C{// array[dim], T size elements, fill bytes with value}§
    6728         T * alloc_set( size_t dim, T fill );                            §\C{// array[dim], T size elements, fill elements with value}§
    6729         T * alloc_set( size_t dim, const T fill[] );            §\C{// array[dim], T size elements, fill elements with array}§
    6730         T * alloc_set( T ptr[], size_t dim, char fill );        §\C{// realloc array[dim], T size elements, fill bytes with value}§
    6731 
    6732         T * alloc_align( size_t align );                                        §\C{// aligned variable, T size}§
    6733         T * alloc_align( size_t align, size_t dim );            §\C{// aligned array[dim], T size elements}§
    6734         T * alloc_align( T ptr[], size_t align );                       §\C{// realloc new aligned array}§
    6735         T * alloc_align( T ptr[], size_t align, size_t dim ); §\C{// realloc new aligned array[dim]}§
    6736 
    6737         T * alloc_align_set( size_t align, char fill );         §\C{// aligned variable, T size, fill bytes with value}§
    6738         T * alloc_align_set( size_t align, T fill );            §\C{// aligned variable, T size, fill with value}§
    6739         T * alloc_align_set( size_t align, size_t dim, char fill ); §\C{// aligned array[dim], T size elements, fill bytes with value}§
    6740         T * alloc_align_set( size_t align, size_t dim, T fill ); §\C{// aligned array[dim], T size elements, fill elements with value}§
    6741         T * alloc_align_set( size_t align, size_t dim, const T fill[] ); §\C{// aligned array[dim], T size elements, fill elements with array}§
    6742         T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); §\C{// realloc new aligned array[dim], fill new bytes with value}§
     6723        T * alloc( void );§\indexc{alloc}§
     6724        T * alloc( size_t dim );
     6725        T * alloc( T ptr[], size_t dim );
     6726        T * alloc_set( char fill );§\indexc{alloc_set}§
     6727        T * alloc_set( T fill );
     6728        T * alloc_set( size_t dim, char fill );
     6729        T * alloc_set( size_t dim, T fill );
     6730        T * alloc_set( size_t dim, const T fill[] );
     6731        T * alloc_set( T ptr[], size_t dim, char fill );
     6732
     6733        T * alloc_align( size_t align );
     6734        T * alloc_align( size_t align, size_t dim );
     6735        T * alloc_align( T ptr[], size_t align ); // aligned realloc array
     6736        T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array
     6737        T * alloc_align_set( size_t align, char fill );
     6738        T * alloc_align_set( size_t align, T fill );
     6739        T * alloc_align_set( size_t align, size_t dim, char fill );
     6740        T * alloc_align_set( size_t align, size_t dim, T fill );
     6741        T * alloc_align_set( size_t align, size_t dim, const T fill[] );
     6742        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill );
    67436743
    67446744        // §\CFA§ safe initialization/copy, i.e., implicit size specification
  • libcfa/prelude/builtins.c

    r223a633 r33c3ded  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct  9 18:26:19 2020
    13 // Update Count     : 110
     12// Last Modified On : Mon Jul 13 21:10:02 2020
     13// Update Count     : 109
    1414//
    1515
     
    9494// universal typed pointer constant
    9595static inline forall( dtype DT ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
    96 static inline forall( ftype FT ) FT * intptr( uintptr_t addr ) { return (FT *)addr; }
    9796
    9897#if defined(__SIZEOF_INT128__)
  • libcfa/src/Makefile.am

    r223a633 r33c3ded  
    8888inst_thread_headers_nosrc = \
    8989        bits/random.hfa \
    90         concurrency/clib/cfathread.h \
    9190        concurrency/invoke.h \
    9291        concurrency/kernel/fwd.hfa
     
    104103        concurrency/alarm.cfa \
    105104        concurrency/alarm.hfa \
    106         concurrency/clib/cfathread.cfa \
    107105        concurrency/CtxSwitch-@ARCHITECTURE@.S \
    108106        concurrency/invoke.c \
  • libcfa/src/bits/containers.hfa

    r223a633 r33c3ded  
    157157                        tail = &get_next( *val );
    158158                        *tail = 1p;
    159                 }
    160 
    161                 T * peek( __queue(T) & this ) {
    162                         verify(*this.tail == 1p);
    163                         T * head = this.head;
    164                         if( head != 1p ) {
    165                                 verify(*this.tail == 1p);
    166                                 return head;
    167                         }
    168                         verify(*this.tail == 1p);
    169                         return 0p;
    170159                }
    171160
  • libcfa/src/bits/locks.hfa

    r223a633 r33c3ded  
    164164
    165165        struct $thread;
    166         extern void park( void );
    167         extern void unpark( struct $thread * this );
     166        extern void park( __cfaabi_dbg_ctx_param );
     167        extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 );
    168168        static inline struct $thread * active_thread ();
    169169
     
    191191                                        /* paranoid */ verify( expected == 0p );
    192192                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    193                                                 park();
     193                                                park( __cfaabi_dbg_ctx );
    194194                                                return true;
    195195                                        }
     
    210210                                else {
    211211                                        if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    212                                                 unpark( expected );
     212                                                unpark( expected __cfaabi_dbg_ctx2 );
    213213                                                return true;
    214214                                        }
     
    244244                                /* paranoid */ verify( expected == 0p );
    245245                                if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    246                                         park();
     246                                        park( __cfaabi_dbg_ctx );
    247247                                        /* paranoid */ verify( this.ptr == 1p );
    248248                                        return true;
     
    256256                        struct $thread * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
    257257                        if( got == 0p ) return false;
    258                         unpark( got );
     258                        unpark( got __cfaabi_dbg_ctx2 );
    259259                        return true;
    260260                }
  • libcfa/src/concurrency/CtxSwitch-i386.S

    r223a633 r33c3ded  
    1010// Created On       : Tue Dec 6 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep  6 18:23:37 2020
    13 // Update Count     : 5
     12// Last Modified On : Sun Aug 16 08:46:22 2020
     13// Update Count     : 4
    1414//
    1515
     
    3535
    3636        // Copy the "from" context argument from the stack to register eax
    37         // Return address is at 0(%esp), with parameters following.
     37        // Return address is at 0(%esp), with parameters following
    3838
    3939        movl 4(%esp),%eax
     
    5050        movl %ebp,FP_OFFSET(%eax)
    5151
    52         // Copy the "to" context argument from the stack to register eax. Having
    53         // pushed 3 words (= 12 bytes) on the stack, the argument is now at
    54         // 8 + 12 = 20(%esp).
     52        // Copy the "to" context argument from the stack to register eax
     53        // Having pushed three words (= 12 bytes) on the stack, the
     54        // argument is now at 8 + 12 = 20(%esp)
    5555
    5656        movl 20(%esp),%eax
  • libcfa/src/concurrency/alarm.cfa

    r223a633 r33c3ded  
    130130
    131131        register_self( &node );
    132         park();
     132        park( __cfaabi_dbg_ctx );
    133133
    134134        /* paranoid */ verify( !node.set );
  • libcfa/src/concurrency/coroutine.cfa

    r223a633 r33c3ded  
    4747
    4848//-----------------------------------------------------------------------------
    49 FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
     49FORALL_DATA_INSTANCE(CoroutineCancelled,
     50                (dtype coroutine_t | sized(coroutine_t)), (coroutine_t))
    5051
    5152struct __cfaehm_node {
     
    5859void mark_exception(CoroutineCancelled(T) *) {}
    5960
    60 forall(dtype T)
     61forall(dtype T | sized(T))
    6162void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
    6263        dst->the_coroutine = src->the_coroutine;
     
    7677        exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
    7778
    78         // TODO: Remove explitate vtable set once trac#186 is fixed.
    7979        CoroutineCancelled(T) except;
    80         except.virtual_table = &get_exception_vtable(&except);
    8180        except.the_coroutine = &cor;
    8281        except.the_exception = except;
     
    9291
    9392// minimum feasible stack size in bytes
    94 static const size_t MinStackSize = 1000;
     93#define MinStackSize 1000
    9594extern size_t __page_size;                              // architecture pagesize HACK, should go in proper runtime singleton
    9695
  • libcfa/src/concurrency/coroutine.hfa

    r223a633 r33c3ded  
    2222//-----------------------------------------------------------------------------
    2323// Exception thrown from resume when a coroutine stack is cancelled.
    24 FORALL_DATA_EXCEPTION(CoroutineCancelled, (dtype coroutine_t), (coroutine_t)) (
     24// Should not have to be be sized (see trac #196).
     25FORALL_DATA_EXCEPTION(CoroutineCancelled,
     26                (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) (
    2527        coroutine_t * the_coroutine;
    2628        exception_t * the_exception;
     
    2830
    2931forall(dtype T)
     32void mark_exception(CoroutineCancelled(T) *);
     33
     34forall(dtype T | sized(T))
    3035void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src);
    3136
     
    3742// Anything that implements this trait can be resumed.
    3843// Anything that is resumed is a coroutine.
    39 trait is_coroutine(dtype T | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) {
     44trait is_coroutine(dtype T | sized(T)
     45                | is_resumption_exception(CoroutineCancelled(T))
     46                | VTABLE_ASSERTION(CoroutineCancelled, (T))) {
    4047        void main(T & this);
    4148        $coroutine * get_coroutine(T & this);
  • libcfa/src/concurrency/invoke.h

    r223a633 r33c3ded  
    9393
    9494        };
    95         // Wrapper for gdb
    96         struct cfathread_coroutine_t { struct $coroutine debug; };
    9795
    9896        static inline struct __stack_t * __get_stack( struct $coroutine * cor ) {
     
    131129                struct __condition_node_t * dtor_node;
    132130        };
    133         // Wrapper for gdb
    134         struct cfathread_monitor_t { struct $monitor debug; };
    135131
    136132        struct __monitor_group_t {
     
    190186                } node;
    191187
    192                 #if defined( __CFA_WITH_VERIFY__ )
    193                         unsigned long long canary;
     188                #ifdef __CFA_DEBUG__
     189                        // previous function to park/unpark the thread
     190                        const char * park_caller;
     191                        int park_result;
     192                        enum __Coroutine_State park_state;
     193                        bool park_stale;
     194                        const char * unpark_caller;
     195                        int unpark_result;
     196                        enum __Coroutine_State unpark_state;
     197                        bool unpark_stale;
    194198                #endif
    195199        };
    196         // Wrapper for gdb
    197         struct cfathread_thread_t { struct $thread debug; };
    198200
    199201        #ifdef __CFA_DEBUG__
  • libcfa/src/concurrency/io.cfa

    r223a633 r33c3ded  
    6969                if( block ) {
    7070                        enable_interrupts( __cfaabi_dbg_ctx );
    71                         park();
     71                        park( __cfaabi_dbg_ctx );
    7272                        disable_interrupts();
    7373                }
     
    9797
    9898                if(nextt) {
    99                         unpark( nextt );
     99                        unpark( nextt __cfaabi_dbg_ctx2 );
    100100                        enable_interrupts( __cfaabi_dbg_ctx );
    101101                        return true;
     
    134134                int ret = 0;
    135135                if( need_sys_to_submit || need_sys_to_complete ) {
    136                         ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, 0, flags, (sigset_t *)0p, _NSIG / 8);
     136                        ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, 0, flags, 0p, _NSIG / 8);
    137137                        if( ret < 0 ) {
    138138                                switch((int)errno) {
  • libcfa/src/concurrency/io/call.cfa.in

    r223a633 r33c3ded  
    4747        #include "kernel/fwd.hfa"
    4848
    49         static const __u8 REGULAR_FLAGS = 0
    50                 #if defined(CFA_HAVE_IOSQE_FIXED_FILE)
    51                         | IOSQE_FIXED_FILE
    52                 #endif
    53                 #if defined(CFA_HAVE_IOSQE_IO_DRAIN)
    54                         | IOSQE_IO_DRAIN
    55                 #endif
    56                 #if defined(CFA_HAVE_IOSQE_ASYNC)
    57                         | IOSQE_ASYNC
    58                 #endif
    59         ;
    60 
    61         static const __u32 LINK_FLAGS = 0
    62                 #if defined(CFA_HAVE_IOSQE_IO_LINK)
    63                         | IOSQE_IO_LINK
    64                 #endif
    65                 #if defined(CFA_HAVE_IOSQE_IO_HARDLINK)
    66                         | IOSQE_IO_HARDLINK
    67                 #endif
    68         ;
    69 
    70         static const __u32 SPLICE_FLAGS = 0
    71                 #if defined(CFA_HAVE_SPLICE_F_FD_IN_FIXED)
    72                         | SPLICE_F_FD_IN_FIXED
    73                 #endif
    74         ;
     49        #if defined(CFA_HAVE_IOSQE_FIXED_FILE) && defined(CFA_HAVE_IOSQE_IO_DRAIN) && defined(CFA_HAVE_IOSQE_ASYNC)
     50                #define REGULAR_FLAGS (IOSQE_FIXED_FILE | IOSQE_IO_DRAIN | IOSQE_ASYNC)
     51        #elif defined(CFA_HAVE_IOSQE_FIXED_FILE) && defined(CFA_HAVE_IOSQE_ASYNC)
     52                #define REGULAR_FLAGS (IOSQE_FIXED_FILE | IOSQE_ASYNC)
     53        #elif defined(CFA_HAVE_IOSQE_FIXED_FILE) && defined(CFA_HAVE_IOSQE_IO_DRAIN)
     54                #define REGULAR_FLAGS (IOSQE_FIXED_FILE | IOSQE_IO_DRAIN)
     55        #elif defined(CFA_HAVE_IOSQE_IO_DRAIN) && defined(CFA_HAVE_IOSQE_ASYNC)
     56                #define REGULAR_FLAGS (IOSQE_IO_DRAIN | IOSQE_ASYNC)
     57        #elif defined(CFA_HAVE_IOSQE_FIXED_FILE)
     58                #define REGULAR_FLAGS (IOSQE_FIXED_FILE)
     59        #elif defined(CFA_HAVE_IOSQE_IO_DRAIN)
     60                #define REGULAR_FLAGS (IOSQE_IO_DRAIN)
     61        #elif defined(CFA_HAVE_IOSQE_ASYNC)
     62                #define REGULAR_FLAGS (IOSQE_ASYNC)
     63        #else
     64                #define REGULAR_FLAGS (0)
     65        #endif
     66
     67        #if defined(CFA_HAVE_IOSQE_IO_LINK) && defined(CFA_HAVE_IOSQE_IO_HARDLINK)
     68                #define LINK_FLAGS (IOSQE_IO_LINK | IOSQE_IO_HARDLINK)
     69        #elif defined(CFA_HAVE_IOSQE_IO_LINK)
     70                #define LINK_FLAGS (IOSQE_IO_LINK)
     71        #elif defined(CFA_HAVE_IOSQE_IO_HARDLINK)
     72                #define LINK_FLAGS (IOSQE_IO_HARDLINK)
     73        #else
     74                #define LINK_FLAGS (0)
     75        #endif
     76
     77        #if defined(CFA_HAVE_SPLICE_F_FD_IN_FIXED)
     78                #define SPLICE_FLAGS (SPLICE_F_FD_IN_FIXED)
     79        #else
     80                #define SPLICE_FLAGS (0)
     81        #endif
    7582
    7683        extern [* struct io_uring_sqe, __u32] __submit_alloc( struct __io_data & ring, __u64 data );
     
    340347        # CFA_HAVE_IORING_OP_MADVISE
    341348        Call('MADVISE', 'int madvise(void *addr, size_t length, int advice)', {
    342                 'addr': '(__u64)addr',
     349                'addr': 'addr',
    343350                'len': 'length',
    344351                'fadvise_advice': 'advice'
  • libcfa/src/concurrency/io/setup.cfa

    r223a633 r33c3ded  
    147147        static void * iopoll_loop( __attribute__((unused)) void * args ) {
    148148                __processor_id_t id;
    149                 id.full_proc = false;
    150149                id.id = doregister(&id);
    151150                __cfaabi_dbg_print_safe( "Kernel : IO poller thread starting\n" );
     
    247246                                        thrd.link.next = 0p;
    248247                                        thrd.link.prev = 0p;
     248                                        __cfaabi_dbg_debug_do( thrd.unpark_stale = true );
    249249
    250250                                        // Fixup the thread state
     
    266266
    267267                                // unpark the fast io_poller
    268                                 unpark( &thrd );
     268                                unpark( &thrd __cfaabi_dbg_ctx2 );
    269269                        }
    270270                        else {
     
    275275                        }
    276276                } else {
    277                         unpark( &thrd );
     277                        unpark( &thrd __cfaabi_dbg_ctx2 );
    278278                }
    279279
  • libcfa/src/concurrency/kernel.cfa

    r223a633 r33c3ded  
    237237        $coroutine * proc_cor = get_coroutine(this->runner);
    238238
     239        // Update global state
     240        kernelTLS.this_thread = thrd_dst;
     241
    239242        // set state of processor coroutine to inactive
    240243        verify(proc_cor->state == Active);
     
    246249                thrd_dst->state = Active;
    247250
    248                 // Update global state
    249                 kernelTLS.this_thread = thrd_dst;
     251                __cfaabi_dbg_debug_do(
     252                        thrd_dst->park_stale   = true;
     253                        thrd_dst->unpark_stale = true;
     254                )
    250255
    251256                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    252257                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
    253                 /* paranoid */ verify( thrd_dst->context.SP );
    254258                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
    255259                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
    256                 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary );
    257 
    258 
    259260
    260261                // set context switch to the thread that the processor is executing
     262                verify( thrd_dst->context.SP );
    261263                __cfactx_switch( &proc_cor->context, &thrd_dst->context );
    262264                // when __cfactx_switch returns we are back in the processor coroutine
    263265
    264                 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary );
    265266                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst );
    266267                /* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ), "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst );
    267                 /* paranoid */ verify( thrd_dst->context.SP );
    268268                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
    269269                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    270270
    271                 // Reset global state
    272                 kernelTLS.this_thread = 0p;
    273271
    274272                // We just finished running a thread, there are a few things that could have happened.
     
    288286                        // The thread has halted, it should never be scheduled/run again
    289287                        // We may need to wake someone up here since
    290                         unpark( this->destroyer );
     288                        unpark( this->destroyer __cfaabi_dbg_ctx2 );
    291289                        this->destroyer = 0p;
    292290                        break RUNNING;
     
    298296                // set state of processor coroutine to active and the thread to inactive
    299297                int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST);
     298                __cfaabi_dbg_debug_do( thrd_dst->park_result = old_ticket; )
    300299                switch(old_ticket) {
    301300                        case 1:
     
    314313        // Just before returning to the processor, set the processor coroutine to active
    315314        proc_cor->state = Active;
     315        kernelTLS.this_thread = 0p;
    316316
    317317        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    334334                        __x87_store;
    335335                #endif
    336                 /* paranoid */ verify( proc_cor->context.SP );
    337                 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary );
     336                verify( proc_cor->context.SP );
    338337                __cfactx_switch( &thrd_src->context, &proc_cor->context );
    339                 /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary );
    340338                #if defined( __i386 ) || defined( __x86_64 )
    341339                        __x87_load;
     
    369367        /* paranoid */ #endif
    370368        /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next );
    371         /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd->canary );
    372 
    373369
    374370        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
     
    407403
    408404// KERNEL ONLY unpark with out disabling interrupts
    409 void __unpark(  struct __processor_id_t * id, $thread * thrd ) {
     405void __unpark(  struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) {
     406        // record activity
     407        __cfaabi_dbg_record_thrd( *thrd, false, caller );
     408
    410409        int old_ticket = __atomic_fetch_add(&thrd->ticket, 1, __ATOMIC_SEQ_CST);
     410        __cfaabi_dbg_debug_do( thrd->unpark_result = old_ticket; thrd->unpark_state = thrd->state; )
    411411        switch(old_ticket) {
    412412                case 1:
     
    426426}
    427427
    428 void unpark( $thread * thrd ) {
     428void unpark( $thread * thrd __cfaabi_dbg_ctx_param2 ) {
    429429        if( !thrd ) return;
    430430
    431431        disable_interrupts();
    432         __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd );
     432        __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2 );
    433433        enable_interrupts( __cfaabi_dbg_ctx );
    434434}
    435435
    436 void park( void ) {
     436void park( __cfaabi_dbg_ctx_param ) {
    437437        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    438438        disable_interrupts();
    439439        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    440440        /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION );
     441
     442        // record activity
     443        __cfaabi_dbg_record_thrd( *kernelTLS.this_thread, true, caller );
    441444
    442445        returnToKernel();
     
    518521        disable_interrupts();
    519522                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    520                 post( this->idle );
     523                bool ret = post( this->idle );
    521524        enable_interrupts( __cfaabi_dbg_ctx );
    522525}
     
    646649                // atomically release spin lock and block
    647650                unlock( lock );
    648                 park();
     651                park( __cfaabi_dbg_ctx );
    649652                return true;
    650653        }
     
    667670
    668671        // make new owner
    669         unpark( thrd );
     672        unpark( thrd __cfaabi_dbg_ctx2 );
    670673
    671674        return thrd != 0p;
     
    678681        count += diff;
    679682        for(release) {
    680                 unpark( pop_head( waiting ) );
     683                unpark( pop_head( waiting ) __cfaabi_dbg_ctx2 );
    681684        }
    682685
     
    694697                        this.prev_thrd = kernelTLS.this_thread;
    695698                }
     699
     700                void __cfaabi_dbg_record_thrd($thread & this, bool park, const char prev_name[]) {
     701                        if(park) {
     702                                this.park_caller   = prev_name;
     703                                this.park_stale    = false;
     704                        }
     705                        else {
     706                                this.unpark_caller = prev_name;
     707                                this.unpark_stale  = false;
     708                        }
     709                }
    696710        }
    697711)
  • libcfa/src/concurrency/kernel.hfa

    r223a633 r33c3ded  
    4848// Processor id, required for scheduling threads
    4949struct __processor_id_t {
    50         unsigned id:24;
    51         bool full_proc:1;
     50        unsigned id;
    5251
    5352        #if !defined(__CFA_NO_STATISTICS__)
  • libcfa/src/concurrency/kernel/fwd.hfa

    r223a633 r33c3ded  
    118118
    119119        extern "Cforall" {
    120                 extern void park( void );
    121                 extern void unpark( struct $thread * this );
     120                extern void park( __cfaabi_dbg_ctx_param );
     121                extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 );
    122122                static inline struct $thread * active_thread () { return TL_GET( this_thread ); }
    123123
  • libcfa/src/concurrency/kernel/startup.cfa

    r223a633 r33c3ded  
    451451        link.next = 0p;
    452452        link.prev = 0p;
    453         #if defined( __CFA_WITH_VERIFY__ )
    454                 canary = 0x0D15EA5E0D15EA5E;
    455         #endif
    456453
    457454        node.next = 0p;
     
    473470        this.name = name;
    474471        this.cltr = &_cltr;
    475         full_proc = true;
     472        id = -1u;
    476473        destroyer = 0p;
    477474        do_terminate = false;
  • libcfa/src/concurrency/kernel_private.hfa

    r223a633 r33c3ded  
    6464
    6565// KERNEL ONLY unpark with out disabling interrupts
    66 void __unpark( struct __processor_id_t *, $thread * thrd );
     66void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2 );
    6767
    6868static inline bool __post(single_sem & this, struct __processor_id_t * id) {
     
    7777                else {
    7878                        if(__atomic_compare_exchange_n(&this.ptr, &expected, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    79                                 __unpark( id, expected );
     79                                __unpark( id, expected __cfaabi_dbg_ctx2 );
    8080                                return true;
    8181                        }
  • libcfa/src/concurrency/monitor.cfa

    r223a633 r33c3ded  
    122122
    123123                unlock( this->lock );
    124                 park();
     124                park( __cfaabi_dbg_ctx );
    125125
    126126                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     
    201201                // Release the next thread
    202202                /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    203                 unpark( urgent->owner->waiting_thread );
     203                unpark( urgent->owner->waiting_thread __cfaabi_dbg_ctx2 );
    204204
    205205                // Park current thread waiting
    206                 park();
     206                park( __cfaabi_dbg_ctx );
    207207
    208208                // Some one was waiting for us, enter
     
    222222
    223223                // Park current thread waiting
    224                 park();
     224                park( __cfaabi_dbg_ctx );
    225225
    226226                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     
    264264        //We need to wake-up the thread
    265265        /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
    266         unpark( new_owner );
     266        unpark( new_owner __cfaabi_dbg_ctx2 );
    267267}
    268268
     
    493493        // Wake the threads
    494494        for(int i = 0; i < thread_count; i++) {
    495                 unpark( threads[i] );
     495                unpark( threads[i] __cfaabi_dbg_ctx2 );
    496496        }
    497497
    498498        // Everything is ready to go to sleep
    499         park();
     499        park( __cfaabi_dbg_ctx );
    500500
    501501        // We are back, restore the owners and recursions
     
    575575
    576576        // unpark the thread we signalled
    577         unpark( signallee );
     577        unpark( signallee __cfaabi_dbg_ctx2 );
    578578
    579579        //Everything is ready to go to sleep
    580         park();
     580        park( __cfaabi_dbg_ctx );
    581581
    582582
     
    679679
    680680                                // unpark the thread we signalled
    681                                 unpark( next );
     681                                unpark( next __cfaabi_dbg_ctx2 );
    682682
    683683                                //Everything is ready to go to sleep
    684                                 park();
     684                                park( __cfaabi_dbg_ctx );
    685685
    686686                                // We are back, restore the owners and recursions
     
    724724
    725725        //Everything is ready to go to sleep
    726         park();
     726        park( __cfaabi_dbg_ctx );
    727727
    728728
  • libcfa/src/concurrency/mutex.cfa

    r223a633 r33c3ded  
    4242                append( blocked_threads, kernelTLS.this_thread );
    4343                unlock( lock );
    44                 park();
     44                park( __cfaabi_dbg_ctx );
    4545        }
    4646        else {
     
    6565        this.is_locked = (this.blocked_threads != 0);
    6666        unpark(
    67                 pop_head( this.blocked_threads )
     67                pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2
    6868        );
    6969        unlock( this.lock );
     
    9797                append( blocked_threads, kernelTLS.this_thread );
    9898                unlock( lock );
    99                 park();
     99                park( __cfaabi_dbg_ctx );
    100100        }
    101101}
     
    124124                owner = thrd;
    125125                recursion_count = (thrd ? 1 : 0);
    126                 unpark( thrd );
     126                unpark( thrd __cfaabi_dbg_ctx2 );
    127127        }
    128128        unlock( lock );
     
    142142        lock( lock __cfaabi_dbg_ctx2 );
    143143        unpark(
    144                 pop_head( this.blocked_threads )
     144                pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2
    145145        );
    146146        unlock( lock );
     
    151151        while(this.blocked_threads) {
    152152                unpark(
    153                         pop_head( this.blocked_threads )
     153                        pop_head( this.blocked_threads ) __cfaabi_dbg_ctx2
    154154                );
    155155        }
     
    161161        append( this.blocked_threads, kernelTLS.this_thread );
    162162        unlock( this.lock );
    163         park();
     163        park( __cfaabi_dbg_ctx );
    164164}
    165165
     
    170170        unlock(l);
    171171        unlock(this.lock);
    172         park();
     172        park( __cfaabi_dbg_ctx );
    173173        lock(l);
    174174}
  • libcfa/src/concurrency/preemption.cfa

    r223a633 r33c3ded  
    274274                kernelTLS.this_stats = this->curr_cluster->stats;
    275275        #endif
    276         __unpark( id, this );
     276        __unpark( id, this __cfaabi_dbg_ctx2 );
    277277}
    278278
     
    411411static void * alarm_loop( __attribute__((unused)) void * args ) {
    412412        __processor_id_t id;
    413         id.full_proc = false;
    414413        id.id = doregister(&id);
    415414
  • libcfa/src/concurrency/snzi.hfa

    r223a633 r33c3ded  
    3636static inline void depart( __snzi_node_t & );
    3737
    38 static const int __snzi_half = -1;
     38#define __snzi_half -1
    3939
    4040//--------------------------------------------------
  • libcfa/src/concurrency/thread.cfa

    r223a633 r33c3ded  
    3939        link.prev = 0p;
    4040        link.preferred = -1;
    41         #if defined( __CFA_WITH_VERIFY__ )
    42                 canary = 0x0D15EA5E0D15EA5E;
    43         #endif
    4441
    4542        node.next = 0p;
     
    5148
    5249void ^?{}($thread& this) with( this ) {
    53         #if defined( __CFA_WITH_VERIFY__ )
    54                 canary = 0xDEADDEADDEADDEAD;
    55         #endif
    5650        unregister(curr_cluster, this);
    5751        ^self_cor{};
  • libcfa/src/concurrency/thread.hfa

    r223a633 r33c3ded  
    8888//----------
    8989// Park thread: block until corresponding call to unpark, won't block if unpark is already called
    90 void park( void );
     90void park( __cfaabi_dbg_ctx_param );
    9191
    9292//----------
    9393// Unpark a thread, if the thread is already blocked, schedule it
    9494//                  if the thread is not yet block, signal that it should rerun immediately
    95 void unpark( $thread * this );
     95void unpark( $thread * this __cfaabi_dbg_ctx_param2 );
    9696
    9797forall( dtype T | is_thread(T) )
    98 static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );}
     98static inline void unpark( T & this __cfaabi_dbg_ctx_param2 ) { if(!&this) return; unpark( get_thread( this ) __cfaabi_dbg_ctx_fwd2 );}
    9999
    100100//----------
  • libcfa/src/exception.h

    r223a633 r33c3ded  
    7676// implemented in the .c file either so they all have to be inline.
    7777
    78 trait is_exception(dtype exceptT, dtype virtualT) {
     78trait is_exception(dtype exceptT) {
    7979        /* The first field must be a pointer to a virtual table.
    80          * That virtual table must be a decendent of the base exception virtual table.
     80         * That virtual table must be a decendent of the base exception virtual tab$
    8181         */
    82         virtualT const & get_exception_vtable(exceptT *);
    83         // Always returns the virtual table for this type (associated types hack).
     82        void mark_exception(exceptT *);
     83        // This is never used and should be a no-op.
    8484};
    8585
    86 trait is_termination_exception(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT)) {
     86trait is_termination_exception(dtype exceptT | is_exception(exceptT)) {
    8787        void defaultTerminationHandler(exceptT &);
    8888};
    8989
    90 trait is_resumption_exception(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT)) {
     90trait is_resumption_exception(dtype exceptT | is_exception(exceptT)) {
    9191        void defaultResumptionHandler(exceptT &);
    9292};
    9393
    94 forall(dtype exceptT, dtype virtualT | is_termination_exception(exceptT, virtualT))
     94forall(dtype exceptT | is_termination_exception(exceptT))
    9595static inline void $throw(exceptT & except) {
    9696        __cfaehm_throw_terminate(
     
    100100}
    101101
    102 forall(dtype exceptT, dtype virtualT | is_resumption_exception(exceptT, virtualT))
     102forall(dtype exceptT | is_resumption_exception(exceptT))
    103103static inline void $throwResume(exceptT & except) {
    104104        __cfaehm_throw_resume(
     
    108108}
    109109
    110 forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
     110forall(dtype exceptT | is_exception(exceptT))
    111111static inline void cancel_stack(exceptT & except) __attribute__((noreturn)) {
    112112        __cfaehm_cancel_stack( (exception_t *)&except );
    113113}
    114114
    115 forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
     115forall(dtype exceptT | is_exception(exceptT))
    116116static inline void defaultTerminationHandler(exceptT & except) {
    117117        return cancel_stack( except );
    118118}
    119119
    120 forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
     120forall(dtype exceptT | is_exception(exceptT))
    121121static inline void defaultResumptionHandler(exceptT & except) {
    122122        throw except;
  • libcfa/src/exception.hfa

    r223a633 r33c3ded  
    9595// visible anywhere you use the instantiation of the exception is used.
    9696#define POLY_VTABLE_DECLARATION(exception_name, ...) \
    97         VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable(exception_name(__VA_ARGS__) *); \
     97        void mark_exception(exception_name(__VA_ARGS__) *); \
    9898        extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name)
    9999
     
    125125#define VTABLE_ASSERTION(exception_name, parameters) \
    126126        { VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); }
    127 
    128 // IS_EXCEPTION(exception_name [, (...parameters)])
    129 // IS_RESUMPTION_EXCEPTION(exception_name [, (parameters...)])
    130 // IS_TERMINATION_EXCEPTION(exception_name [, (parameters...)])
    131 // Create an assertion that exception_name, possibly with the qualifing parameters, is the given
    132 // kind of exception with the standard vtable with the same parameters if applicable.
    133 #define IS_EXCEPTION(...) _IS_EXCEPTION(is_exception, __VA_ARGS__, , ~)
    134 #define IS_RESUMPTION_EXCEPTION(...) _IS_EXCEPTION(is_resumption_exception, __VA_ARGS__, , ~)
    135 #define IS_TERMINATION_EXCEPTION(...) _IS_EXCEPTION(is_termination_exception, __VA_ARGS__, , ~)
    136127
    137128// All internal helper macros begin with an underscore.
     
    169160
    170161#define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \
    171         forall(_UNPACK assertions | \
    172                 is_exception(exception_name parameters, VTABLE_TYPE(exception_name) parameters)) \
     162        forall(_UNPACK assertions | VTABLE_ASSERTION(exception_name, parameters) ) \
    173163        void ?{}(exception_name parameters & this)
    174164
    175165#define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \
    176166        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \
    177                 (this).virtual_table = &get_exception_vtable(&this); \
     167                VTABLE_INIT(this, exception_name); \
    178168        }
    179169
     
    195185#define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
    196186        struct exception_name; \
     187        void mark_exception(exception_name *); \
    197188        VTABLE_TYPE(exception_name); \
    198         VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *); \
    199189        extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
    200190        VTABLE_TYPE(exception_name) { \
     
    207197
    208198#define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
    209         VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *) { \
    210                 return VTABLE_NAME(exception_name); \
    211         } \
     199        void mark_exception(exception_name *) {} \
    212200        void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
    213201                *this = *other; \
     
    230218
    231219#define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \
    232         extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name); \
    233         VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable( \
    234                         exception_name(__VA_ARGS__) *) { \
    235                 return VTABLE_NAME(exception_name); \
    236         } \
     220        void mark_exception(exception_name(__VA_ARGS__) *) {} \
    237221        void _GLUE2(exception_name,_copy)( \
    238222                        exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \
     
    243227                _GLUE2(exception_name,_copy), ^?{}, \
    244228                _CLOSE
    245 
    246 #define _IS_EXCEPTION(kind, exception_name, parameters, ...) \
    247         kind(exception_name parameters, VTABLE_TYPE(exception_name) parameters)
  • libcfa/src/parseargs.cfa

    r223a633 r33c3ded  
    2525#include "limits.hfa"
    2626
    27 extern int cfa_args_argc __attribute__((weak));
    28 extern char ** cfa_args_argv __attribute__((weak));
    29 extern char ** cfa_args_envp __attribute__((weak));
     27extern int cfa_args_argc;
     28extern char ** cfa_args_argv;
     29extern char ** cfa_args_envp;
    3030
    3131static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out)  __attribute__ ((noreturn));
    3232
    3333void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) {
    34         if( 0p != &cfa_args_argc ) {
    35                 parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
    36         }
    37         else {
    38                 char * temp = "";
    39                 parse_args(0, &temp, options, opt_count, usage, left );
    40         }
     34        parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
    4135}
    4236
  • src/AST/Convert.cpp

    r223a633 r33c3ded  
    177177        const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
    178178                if ( inCache( node ) ) return nullptr;
    179 
    180                 // function decl contains real variables that the type must use.
    181                 // the structural change means function type in and out of decl
    182                 // must be handled **differently** on convert back to old.
    183                 auto ftype = new FunctionType(
    184                         cv(node->type),
    185                         (bool)node->type->isVarArgs
    186                 );
    187                 ftype->returnVals = get<DeclarationWithType>().acceptL(node->returns);
    188                 ftype->parameters = get<DeclarationWithType>().acceptL(node->params);
    189 
    190                 ftype->forall = get<TypeDecl>().acceptL( node->type->forall );
    191 
    192                 visitType(node->type, ftype);
    193 
    194179                auto decl = new FunctionDecl(
    195180                        node->name,
    196181                        Type::StorageClasses( node->storage.val ),
    197182                        LinkageSpec::Spec( node->linkage.val ),
    198                         ftype,
    199                         //get<FunctionType>().accept1( node->type ),
     183                        get<FunctionType>().accept1( node->type ),
    200184                        {},
    201185                        get<Attribute>().acceptL( node->attributes ),
     
    11681152
    11691153        const ast::Type * visit( const ast::FunctionType * node ) override final {
    1170                 static std::string dummy_paramvar_prefix = "__param_";
    1171                 static std::string dummy_returnvar_prefix = "__retval_";
    1172 
    11731154                auto ty = new FunctionType {
    11741155                        cv( node ),
    11751156                        (bool)node->isVarArgs
    11761157                };
    1177                 auto returns = get<Type>().acceptL(node->returns);
    1178                 auto params = get<Type>().acceptL(node->params);
    1179 
    1180                 int ret_index = 0;
    1181                 for (auto t: returns) {
    1182                         // xxx - LinkageSpec shouldn't matter but needs to be something
    1183                         ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
    1184                         ty->returnVals.push_back(dummy);
    1185                 }
    1186                 int param_index = 0;
    1187                 for (auto t: params) {
    1188                         ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr);
    1189                         ty->parameters.push_back(dummy);
    1190                 }
    1191 
    1192                 // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
    1193                 // ty->parameters = get<DeclarationWithType>().acceptL( node->params );
     1158                ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
     1159                ty->parameters = get<DeclarationWithType>().acceptL( node->params );
    11941160                ty->forall = get<TypeDecl>().acceptL( node->forall );
    11951161                return visitType( node, ty );
     
    14081374        ast::Node * node = nullptr;
    14091375        /// cache of nodes that might be referenced by readonly<> for de-duplication
    1410         /// in case that some nodes are dropped by conversion (due to possible structural change)
    1411         /// use smart pointers in cache value to prevent accidental invalidation.
    1412         /// at conversion stage, all created nodes are guaranteed to be unique, therefore
    1413         /// const_casting out of smart pointers is permitted.
    1414         std::unordered_map< const BaseSyntaxNode *, ast::ptr<ast::Node> > cache = {};
     1376        std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
    14151377
    14161378        // Local Utilities:
     
    14851447                auto it = cache.find( old );
    14861448                if ( it == cache.end() ) return false;
    1487                 node = const_cast<ast::Node *>(it->second.get());
     1449                node = it->second;
    14881450                return true;
    14891451        }
     
    15241486        virtual void visit( const FunctionDecl * old ) override final {
    15251487                if ( inCache( old ) ) return;
    1526                 auto paramVars = GET_ACCEPT_V(type->parameters, DeclWithType);
    1527                 auto returnVars = GET_ACCEPT_V(type->returnVals, DeclWithType);
    1528                 auto forall = GET_ACCEPT_V(type->forall, TypeDecl);
    1529 
    1530                 // function type is now derived from parameter decls instead of storing them
    1531                 auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
    1532                 ftype->params.reserve(paramVars.size());
    1533                 ftype->returns.reserve(returnVars.size());
    1534 
    1535                 for (auto & v: paramVars) {
    1536                         ftype->params.emplace_back(v->get_type());
    1537                 }
    1538                 for (auto & v: returnVars) {
    1539                         ftype->returns.emplace_back(v->get_type());
    1540                 }
    1541                 ftype->forall = std::move(forall);
    1542                 visitType(old->type, ftype);
    1543 
    15441488                auto decl = new ast::FunctionDecl{
    15451489                        old->location,
    15461490                        old->name,
    1547                         // GET_ACCEPT_1(type, FunctionType),
    1548                         std::move(paramVars),
    1549                         std::move(returnVars),
     1491                        GET_ACCEPT_1(type, FunctionType),
    15501492                        {},
    15511493                        { old->storageClasses.val },
     
    15541496                        { old->get_funcSpec().val }
    15551497                };
    1556 
    1557                 decl->type = ftype;
    15581498                cache.emplace( old, decl );
    1559 
    15601499                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    15611500                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    25762515                        cv( old )
    25772516                };
    2578                 auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType);
    2579                 auto paramVars = GET_ACCEPT_V(parameters, DeclWithType);
    2580                 // ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
    2581                 // ty->params = GET_ACCEPT_V( parameters, DeclWithType );
    2582                 for (auto & v: returnVars) {
    2583                         ty->returns.emplace_back(v->get_type());
    2584                 }
    2585                 for (auto & v: paramVars) {
    2586                         ty->params.emplace_back(v->get_type());
    2587                 }
     2517                ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
     2518                ty->params = GET_ACCEPT_V( parameters, DeclWithType );
    25882519                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    25892520                visitType( old, ty );
  • src/AST/Decl.hpp

    r223a633 r33c3ded  
    124124class FunctionDecl : public DeclWithType {
    125125public:
    126         std::vector<ptr<DeclWithType>> params;
    127         std::vector<ptr<DeclWithType>> returns;
    128         // declared type, derived from parameter declarations
    129126        ptr<FunctionType> type;
    130127        ptr<CompoundStmt> stmts;
    131128        std::vector< ptr<Expr> > withExprs;
    132129
    133         FunctionDecl( const CodeLocation & loc, const std::string & name,
    134                 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     130        FunctionDecl( const CodeLocation & loc, const std::string & name, FunctionType * type,
    135131                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    136132                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
    137         : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     133        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
    138134          stmts( stmts ) {}
    139135
  • src/AST/ForallSubstitutor.hpp

    r223a633 r33c3ded  
    3333        }
    3434
    35         template<typename node_t >
    36         std::vector<ptr<node_t>> operator() (const std::vector<ptr<node_t>> & o) {
    37                 std::vector<ptr<node_t>> n;
    38                 n.reserve(o.size());
    39                 for (const node_t * d : o) { n.emplace_back(d->accept(*visitor)); }
    40                 return n;
    41         }
    42        
    43         /*
    44 
    4535        /// Substitute parameter/return type
    4636        std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) {
     
    5848                return n;
    5949        }
    60 
    61         */
    6250};
    6351
  • src/AST/Pass.impl.hpp

    r223a633 r33c3ded  
    465465                        __pass::symtab::addId( core, 0, func );
    466466                        VISIT(
    467                                 // parameter declarations are now directly here
    468                                 maybe_accept( node, &FunctionDecl::params );
    469                                 maybe_accept( node, &FunctionDecl::returns );
    470                                 // foralls are still in function type
    471467                                maybe_accept( node, &FunctionDecl::type );
    472468                                // function body needs to have the same scope as parameters - CompoundStmt will not enter
  • src/AST/SymbolTable.cpp

    r223a633 r33c3ded  
    335335}
    336336
    337 /*
    338337void SymbolTable::addFunctionType( const FunctionType * ftype ) {
    339338        addTypes( ftype->forall );
     
    341340        addIds( ftype->params );
    342341}
    343 */
    344342
    345343void SymbolTable::lazyInitScope() {
     
    370368                assert( ! params.empty() );
    371369                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    372                 const Type * base = InitTweak::getPointerBase( params.front() );
     370                const Type * base = InitTweak::getPointerBase( params.front()->get_type() );
    373371                assert( base );
    374372                return Mangle::mangle( base );
  • src/AST/SymbolTable.hpp

    r223a633 r33c3ded  
    145145
    146146        /// convenience function for adding all of the declarations in a function type to the indexer
    147         // void addFunctionType( const FunctionType * ftype );
     147        void addFunctionType( const FunctionType * ftype );
    148148
    149149private:
  • src/AST/Type.cpp

    r223a633 r33c3ded  
    102102// --- FunctionType
    103103
    104 
    105104FunctionType::FunctionType( const FunctionType & o )
    106105: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     
    113112
    114113namespace {
    115         bool containsTtype( const std::vector<ptr<Type>> & l ) {
     114        bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) {
    116115                if ( ! l.empty() ) {
    117                         return Tuples::isTtype( l.back() );
     116                        return Tuples::isTtype( l.back()->get_type() );
    118117                }
    119118                return false;
  • src/AST/Type.hpp

    r223a633 r33c3ded  
    302302class FunctionType final : public ParameterizedType {
    303303public:
    304 //      std::vector<ptr<DeclWithType>> returns;
    305 //      std::vector<ptr<DeclWithType>> params;
    306 
    307         std::vector<ptr<Type>> returns;
    308         std::vector<ptr<Type>> params;
     304        std::vector<ptr<DeclWithType>> returns;
     305        std::vector<ptr<DeclWithType>> params;
    309306
    310307        /// Does the function accept a variable number of arguments following the arguments specified
  • src/Concurrency/Keywords.cc

    r223a633 r33c3ded  
    6666                        bool needs_main, AggregateDecl::Aggregate cast_target ) :
    6767                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
    68                   context_error( context_error ), exception_name( exception_name ),
    69                   vtable_name( getVTableName( exception_name ) ),
     68                  context_error( context_error ), vtable_name( getVTableName( exception_name ) ),
    7069                  needs_main( needs_main ), cast_target( cast_target ) {}
    7170
     
    9089                const std::string getter_name;
    9190                const std::string context_error;
    92                 const std::string exception_name;
    9391                const std::string vtable_name;
    9492                bool needs_main;
     
    9795                StructDecl   * type_decl = nullptr;
    9896                FunctionDecl * dtor_decl = nullptr;
    99                 StructDecl * except_decl = nullptr;
    10097                StructDecl * vtable_decl = nullptr;
    10198        };
     
    379376                else if ( is_target(decl) ) {
    380377                        handle( decl );
    381                 }
    382                 else if ( !except_decl && exception_name == decl->name && decl->body ) {
    383                         except_decl = decl;
    384378                }
    385379                else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
     
    404398                        assert( struct_type );
    405399
    406                         std::list< Expression * > poly_args = { new TypeExpr( struct_type->clone() ) };
    407                         ObjectDecl * vtable_object = Virtual::makeVtableInstance(
    408                                 vtable_decl->makeInst( poly_args ), struct_type, nullptr );
    409                         declsToAddAfter.push_back( vtable_object );
    410                         declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
    411                                 vtable_object, except_decl->makeInst( std::move( poly_args ) )
    412                         ) );
     400                        declsToAddAfter.push_back( Virtual::makeVtableInstance( vtable_decl, {
     401                                new TypeExpr( struct_type->clone() ),
     402                        }, struct_type, nullptr ) );
    413403                }
    414404
     
    444434        void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
    445435                if ( vtable_decl ) {
    446                         std::list< Expression * > poly_args = {
     436                        declsToAddBefore.push_back( Virtual::makeVtableForward( vtable_decl, {
    447437                                new TypeExpr( new StructInstType( noQualifiers, decl ) ),
    448                         };
    449                         declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
    450                                 vtable_decl->makeInst( poly_args ),
    451                                 except_decl->makeInst( poly_args )
    452                         ) );
    453                         declsToAddBefore.push_back( Virtual::makeVtableForward(
    454                                 vtable_decl->makeInst( move( poly_args ) ) ) );
     438                        } ) );
    455439                // Its only an error if we want a vtable and don't have one.
    456440                } else if ( ! vtable_name.empty() ) {
  • src/GenPoly/InstantiateGeneric.cc

    r223a633 r33c3ded  
    172172                InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
    173173                /// Set of types which are dtype-only generic (and therefore have static layout)
    174                 std::set<AggregateDecl *> dtypeStatics;
     174                ScopedSet< AggregateDecl* > dtypeStatics;
    175175                /// Namer for concrete types
    176176                UniqueName typeNamer;
     
    505505        void GenericInstantiator::beginScope() {
    506506                instantiations.beginScope();
     507                dtypeStatics.beginScope();
    507508        }
    508509
    509510        void GenericInstantiator::endScope() {
    510511                instantiations.endScope();
     512                dtypeStatics.endScope();
    511513        }
    512514
  • src/InitTweak/FixGlobalInit.cc

    r223a633 r33c3ded  
    112112                        } // if
    113113                        if ( Statement * ctor = ctorInit->ctor ) {
    114                                 // Translation 1: Add this attribute on the global declaration:
    115                                 //    __attribute__((section (".data#")))
    116                                 // which makes gcc put the global in the data section,
    117                                 // so that the global is writeable (via a const cast) in the init function.
    118                                 // The trailing # is an injected assembly comment, to suppress the "a" in
    119                                 //    .section .data,"a"
    120                                 //    .section .data#,"a"
    121                                 // to avoid assembler warning "ignoring changed section attributes for .data"
    122                                 Type *strLitT = new PointerType( Type::Qualifiers( ),
    123                                         new BasicType( Type::Qualifiers( ), BasicType::Char ) );
    124                                 std::list< Expression * > attr_params;
    125                                 attr_params.push_back(
    126                                         new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
    127                                 objDecl->attributes.push_back(new Attribute("section", attr_params));
    128                                 // Translation 2: Move the initizliation off the global declaration,
    129                                 // into the startup function.
    130114                                initStatements.push_back( ctor );
    131115                                objDecl->init = nullptr;
  • src/InitTweak/InitTweak.cc

    r223a633 r33c3ded  
    10261026                if ( ftype->params.size() != 2 ) return false;
    10271027
    1028                 const ast::Type * t1 = getPointerBase( ftype->params.front() );
     1028                const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() );
    10291029                if ( ! t1 ) return false;
    1030                 const ast::Type * t2 = ftype->params.back();
     1030                const ast::Type * t2 = ftype->params.back()->get_type();
    10311031
    10321032                return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
  • src/Parser/DeclarationNode.cc

    r223a633 r33c3ded  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Oct  8 08:03:38 2020
    13 // Update Count     : 1135
     12// Last Modified On : Tue Jun  9 20:26:55 2020
     13// Update Count     : 1134
    1414//
    1515
     
    10161016                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    10171017                                dwt->location = cur->location;
    1018                                 *out++ = dwt;
     1018                                * out++ = dwt;
    10191019                        } else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
    10201020                                // e.g., int foo(struct S) {}
     
    10221022                                auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    10231023                                obj->location = cur->location;
    1024                                 *out++ = obj;
     1024                                * out++ = obj;
    10251025                                delete agg;
    10261026                        } else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
     
    10291029                                auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    10301030                                obj->location = cur->location;
    1031                                 *out++ = obj;
     1031                                * out++ = obj;
    10321032                        } else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) {
    10331033                                // e.g., int foo(enum E) {}
     
    10351035                                auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    10361036                                obj->location = cur->location;
    1037                                 *out++ = obj;
     1037                                * out++ = obj;
    10381038                        } // if
    10391039                } catch( SemanticErrorException & e ) {
  • src/Parser/lex.ll

    r223a633 r33c3ded  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Tue Oct  6 18:15:41 2020
    13  * Update Count     : 743
     12 * Last Modified On : Sat Feb 15 11:05:50 2020
     13 * Update Count     : 737
    1414 */
    1515
     
    6262#define IDENTIFIER_RETURN()     RETURN_VAL( typedefTable.isKind( yytext ) )
    6363
    64 #ifdef HAVE_KEYWORDS_FLOATXX                                                    // GCC >= 7 => keyword, otherwise typedef
     64#ifdef HAVE_KEYWORDS_FLOATXX                                                            // GCC >= 7 => keyword, otherwise typedef
    6565#define FLOATXX(v) KEYWORD_RETURN(v);
    6666#else
     
    292292__restrict__    { KEYWORD_RETURN(RESTRICT); }                   // GCC
    293293return                  { KEYWORD_RETURN(RETURN); }
    294  /* resume                      { KEYWORD_RETURN(RESUME); }                             // CFA */
     294        /* resume                       { KEYWORD_RETURN(RESUME); }                             // CFA */
    295295short                   { KEYWORD_RETURN(SHORT); }
    296296signed                  { KEYWORD_RETURN(SIGNED); }
  • src/Parser/parser.yy

    r223a633 r33c3ded  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct  9 18:09:09 2020
    13 // Update Count     : 4614
     12// Last Modified On : Thu May 28 12:11:45 2020
     13// Update Count     : 4500
    1414//
    1515
     
    204204                        return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
    205205                } else {
    206                         SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
     206                        SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
    207207                } // if
    208208        } else {
    209                 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
     209                SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
    210210        } // if
    211211} // forCtrl
     
    278278%token OTYPE FTYPE DTYPE TTYPE TRAIT                                    // CFA
    279279%token SIZEOF OFFSETOF
    280 // %token RESUME                                                                                        // CFA
    281 %token SUSPEND                                                                                  // CFA
     280// %token RESUME                                                                        // CFA
     281%token SUSPEND                                                                  // CFA
    282282%token ATTRIBUTE EXTENSION                                                              // GCC
    283283%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
     
    329329%type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
    330330%type<en> comma_expression                              comma_expression_opt
    331 %type<en> argument_expression_list_opt  argument_expression                     default_initialize_opt
     331%type<en> argument_expression_list_opt          argument_expression                     default_initialize_opt
    332332%type<ifctl> if_control_expression
    333333%type<fctl> for_control_expression              for_control_expression_list
     
    370370%type<decl> assertion assertion_list assertion_list_opt
    371371
    372 %type<en> bit_subrange_size_opt bit_subrange_size
     372%type<en>   bit_subrange_size_opt bit_subrange_size
    373373
    374374%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type
     
    793793        | '(' aggregate_control '&' ')' cast_expression         // CFA
    794794                { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
     795                // VIRTUAL cannot be opt because of look ahead issues
    795796        | '(' VIRTUAL ')' cast_expression                                       // CFA
    796797                { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild< Expression >( $4 ), maybeMoveBuildType( nullptr ) ) ); }
     
    919920        | unary_expression assignment_operator assignment_expression
    920921                {
    921 //                      if ( $2 == OperKinds::AtAssn ) {
    922 //                              SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
    923 //                      } else {
     922                        if ( $2 == OperKinds::AtAssn ) {
     923                                SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
     924                        } else {
    924925                                $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );
    925 //                      } // if
     926                        } // if
    926927                }
    927928        | unary_expression '=' '{' initializer_list_opt comma_opt '}'
     
    16751676
    16761677typedef_expression:
    1677                 // deprecated GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
     1678                // GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
    16781679        TYPEDEF identifier '=' assignment_expression
    16791680                {
    1680                         SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     1681                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
     1682                        SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
    16811683                }
    16821684        | typedef_expression pop ',' push identifier '=' assignment_expression
    16831685                {
    1684                         SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    1685                 }
    1686         ;
     1686                        // $$ = DeclarationNode::newName( 0 );                  // unimplemented
     1687                        SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
     1688                }
     1689        ;
     1690
     1691//c_declaration:
     1692//      declaring_list pop ';'
     1693//      | typedef_declaration pop ';'
     1694//      | typedef_expression pop ';'                                            // GCC, naming expression type
     1695//      | sue_declaration_specifier pop ';'
     1696//      ;
     1697//
     1698//declaring_list:
     1699//              // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static
     1700//              // storage-class
     1701//       declarator asm_name_opt initializer_opt
     1702//              {
     1703//                      typedefTable.addToEnclosingScope( IDENTIFIER );
     1704//                      $$ = ( $2->addType( $1 ))->addAsmName( $3 )->addInitializer( $4 );
     1705//              }
     1706//      | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
     1707//              {
     1708//                      typedefTable.addToEnclosingScope( IDENTIFIER );
     1709//                      $$ = $1->appendList( $1->cloneBaseType( $4->addAsmName( $5 )->addInitializer( $6 ) ) );
     1710//              }
     1711//      ;
    16871712
    16881713c_declaration:
     
    16901715                { $$ = distAttr( $1, $2 ); }
    16911716        | typedef_declaration
    1692         | typedef_expression                                                            // deprecated GCC, naming expression type
     1717        | typedef_expression                                                            // GCC, naming expression type
    16931718        | sue_declaration_specifier
    16941719        ;
     
    20692094                { yyy = true; $$ = AggregateDecl::Union; }
    20702095        | EXCEPTION                                                                                     // CFA
    2071                 // { yyy = true; $$ = AggregateDecl::Exception; }
    2072                 { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2096                { yyy = true; $$ = AggregateDecl::Exception; }
    20732097        ;
    20742098
     
    24122436// Overloading: function, data, and operator identifiers may be overloaded.
    24132437//
    2414 // Type declarations: "otype" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
     2438// Type declarations: "type" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
    24152439//     and incomplete types, and "ftype" is used for function types. Type declarations with initializers provide
    24162440//     definitions of new types. Type declarations with storage class "extern" provide opaque types.
     
    24412465        type_class identifier_or_type_name
    24422466                { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
    2443         type_initializer_opt assertion_list_opt
     2467          type_initializer_opt assertion_list_opt
    24442468                { $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
    24452469        | type_specifier identifier_parameter_declarator
     
    24682492        assertion
    24692493        | assertion_list assertion
    2470                 { $$ = $1->appendList( $2 ); }
     2494                { $$ = $1 ? $1->appendList( $2 ) : $2; }
    24712495        ;
    24722496
  • src/ResolvExpr/CandidateFinder.cpp

    r223a633 r33c3ded  
    188188
    189189                        // mark conversion cost and also specialization cost of param type
    190                         // const ast::Type * paramType = (*param)->get_type();
     190                        const ast::Type * paramType = (*param)->get_type();
    191191                        cand->expr = ast::mutate_field_index(
    192192                                appExpr, &ast::ApplicationExpr::args, i,
    193193                                computeExpressionConversionCost(
    194                                         args[i], *param, symtab, cand->env, convCost ) );
    195                         convCost.decSpec( specCost( *param ) );
     194                                        args[i], paramType, symtab, cand->env, convCost ) );
     195                        convCost.decSpec( specCost( paramType ) );
    196196                        ++param;  // can't be in for-loop update because of the continue
    197197                }
     
    698698                        if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {
    699699                                // attempt to narrow based on expected target type
    700                                 const ast::Type * returnType = funcType->returns.front();
     700                                const ast::Type * returnType = funcType->returns.front()->get_type();
    701701                                if ( ! unify(
    702702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     
    712712                        std::size_t genStart = 0;
    713713
    714                         // xxx - how to handle default arg after change to ftype representation?
    715                         if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {
    716                                 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {
    717                                         // function may have default args only if directly calling by name
    718                                         // must use types on candidate however, due to RenameVars substitution
    719                                         auto nParams = funcType->params.size();
    720 
    721                                         for (size_t i=0; i<nParams; ++i) {
    722                                                 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    723                                                 if (!instantiateArgument(
    724                                                         funcType->params[i], obj->init, args, results, genStart, symtab)) return;
    725                                         }
    726                                         goto endMatch;
    727                                 }
    728                         }
    729                         for ( const auto & param : funcType->params ) {
     714                        for ( const ast::DeclWithType * param : funcType->params ) {
     715                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    730716                                // Try adding the arguments corresponding to the current parameter to the existing
    731717                                // matches
    732                                 // no default args for indirect calls
    733718                                if ( ! instantiateArgument(
    734                                         param, nullptr, args, results, genStart, symtab ) ) return;
    735                         }
    736 
    737                         endMatch:
     719                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
     720                        }
     721
    738722                        if ( funcType->isVarArgs ) {
    739723                                // append any unused arguments to vararg pack
  • src/ResolvExpr/CurrentObject.cc

    r223a633 r33c3ded  
    594594        class SimpleIterator final : public MemberIterator {
    595595                CodeLocation location;
    596                 const Type * type = nullptr;
     596                readonly< Type > type = nullptr;
    597597        public:
    598598                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
     
    630630        class ArrayIterator final : public MemberIterator {
    631631                CodeLocation location;
    632                 const ArrayType * array = nullptr;
    633                 const Type * base = nullptr;
     632                readonly< ArrayType > array = nullptr;
     633                readonly< Type > base = nullptr;
    634634                size_t index = 0;
    635635                size_t size = 0;
  • src/ResolvExpr/ResolveAssertions.cc

    r223a633 r33c3ded  
    277277                        const DeclarationWithType * candidate = cdata.id;
    278278
    279                         // ignore deleted candidates.
    280                         // NOTE: this behavior is different from main resolver.
    281                         // further investigations might be needed to determine
    282                         // if we should implement the same rule here
    283                         // (i.e. error if unique best match is deleted)
    284                         if (candidate->isDeleted) continue;
    285 
    286                         // build independent unification context. for candidate
     279                        // build independent unification context for candidate
    287280                        AssertionSet have, newNeed;
    288281                        TypeEnvironment newEnv{ resn.alt.env };
  • src/ResolvExpr/Resolver.cc

    r223a633 r33c3ded  
    12231223                template<typename Iter>
    12241224                inline bool nextMutex( Iter & it, const Iter & end ) {
    1225                         while ( it != end && ! (*it)->is_mutex() ) { ++it; }
     1225                        while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
    12261226                        return it != end;
    12271227                }
     
    16381638                                                                // Check if the argument matches the parameter type in the current
    16391639                                                                // scope
    1640                                                                 // ast::ptr< ast::Type > paramType = (*param)->get_type();
     1640                                                                ast::ptr< ast::Type > paramType = (*param)->get_type();
    16411641                                                                if (
    16421642                                                                        ! unify(
    1643                                                                                 arg->expr->result, *param, resultEnv, need, have, open,
     1643                                                                                arg->expr->result, paramType, resultEnv, need, have, open,
    16441644                                                                                symtab )
    16451645                                                                ) {
     
    16481648                                                                        ss << "candidate function not viable: no known conversion "
    16491649                                                                                "from '";
    1650                                                                         ast::print( ss, *param );
     1650                                                                        ast::print( ss, (*param)->get_type() );
    16511651                                                                        ss << "' to '";
    16521652                                                                        ast::print( ss, arg->expr->result );
  • src/ResolvExpr/SatisfyAssertions.cpp

    r223a633 r33c3ded  
    170170                        const ast::DeclWithType * candidate = cdata.id;
    171171
    172                         // ignore deleted candidates.
    173                         // NOTE: this behavior is different from main resolver.
    174                         // further investigations might be needed to determine
    175                         // if we should implement the same rule here
    176                         // (i.e. error if unique best match is deleted)
    177                         if (candidate->isDeleted) continue;
    178 
    179172                        // build independent unification context for candidate
    180173                        ast::AssertionSet have, newNeed;
     
    325318                                        if ( ! func ) continue;
    326319
    327                                         for ( const auto & param : func->params ) {
    328                                                 cost.decSpec( specCost( param ) );
     320                                        for ( const ast::DeclWithType * param : func->params ) {
     321                                                cost.decSpec( specCost( param->get_type() ) );
    329322                                        }
    330323
  • src/ResolvExpr/SpecCost.cc

    r223a633 r33c3ded  
    178178                void previsit( const ast::FunctionType * fty ) {
    179179                        int minCount = std::numeric_limits<int>::max();
    180                         updateMinimumPresent( minCount, fty->params, type_deref );
    181                         updateMinimumPresent( minCount, fty->returns, type_deref );
     180                        updateMinimumPresent( minCount, fty->params, decl_type );
     181                        updateMinimumPresent( minCount, fty->returns, decl_type );
    182182                        // Add another level to minCount if set.
    183183                        count = toNoneOrInc( minCount );
  • src/ResolvExpr/Unify.cc

    r223a633 r33c3ded  
    395395
    396396        template< typename Iterator1, typename Iterator2 >
    397         bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     397        bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    398398                auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    399399                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     
    489489                                        || flatOther->isTtype()
    490490                        ) {
    491                                 if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    492                                         if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     491                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     492                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    493493
    494494                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    784784
    785785                /// returns flattened version of `src`
    786                 static std::vector< ast::ptr< ast::Type > > flattenList(
    787                         const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     786                static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
     787                        const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
    788788                ) {
    789                         std::vector< ast::ptr< ast::Type > > dst;
     789                        std::vector< ast::ptr< ast::DeclWithType > > dst;
    790790                        dst.reserve( src.size() );
    791                         for ( const auto & d : src ) {
     791                        for ( const ast::DeclWithType * d : src ) {
    792792                                ast::Pass<TtypeExpander_new> expander{ env };
    793793                                // TtypeExpander pass is impure (may mutate nodes in place)
    794794                                // need to make nodes shared to prevent accidental mutation
    795                                 ast::ptr<ast::Type> dc = d->accept(expander);
    796                                 auto types = flatten( dc );
     795                                ast::ptr<ast::DeclWithType> dc = d->accept(expander);
     796                                auto types = flatten( dc->get_type() );
    797797                                for ( ast::ptr< ast::Type > & t : types ) {
    798798                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     
    803803                                        // requirements than a non-mutex function
    804804                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    805                                         dst.emplace_back( t );
     805                                        dst.emplace_back( new ast::ObjectDecl{ dc->location, "", t } );
    806806                                }
    807807                        }
     
    811811                /// Creates a tuple type based on a list of DeclWithType
    812812                template< typename Iter >
    813                 static ast::ptr< ast::Type > tupleFromTypes( Iter crnt, Iter end ) {
     813                static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
    814814                        std::vector< ast::ptr< ast::Type > > types;
    815815                        while ( crnt != end ) {
    816816                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    817817                                // that this results in a flat tuple
    818                                 flatten( *crnt, types );
     818                                flatten( (*crnt)->get_type(), types );
    819819
    820820                                ++crnt;
     
    825825
    826826                template< typename Iter >
    827                 static bool unifyTypeList(
     827                static bool unifyDeclList(
    828828                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    829829                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     
    831831                ) {
    832832                        while ( crnt1 != end1 && crnt2 != end2 ) {
    833                                 const ast::Type * t1 = *crnt1;
    834                                 const ast::Type * t2 = *crnt2;
     833                                const ast::Type * t1 = (*crnt1)->get_type();
     834                                const ast::Type * t2 = (*crnt2)->get_type();
    835835                                bool isTuple1 = Tuples::isTtype( t1 );
    836836                                bool isTuple2 = Tuples::isTtype( t2 );
     
    840840                                        // combine remainder of list2, then unify
    841841                                        return unifyExact(
    842                                                 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
     842                                                t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    843843                                                noWiden(), symtab );
    844844                                } else if ( ! isTuple1 && isTuple2 ) {
    845845                                        // combine remainder of list1, then unify
    846846                                        return unifyExact(
    847                                                 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
     847                                                tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    848848                                                noWiden(), symtab );
    849849                                }
     
    860860                        if ( crnt1 != end1 ) {
    861861                                // try unifying empty tuple with ttype
    862                                 const ast::Type * t1 = *crnt1;
     862                                const ast::Type * t1 = (*crnt1)->get_type();
    863863                                if ( ! Tuples::isTtype( t1 ) ) return false;
    864864                                return unifyExact(
    865                                         t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
     865                                        t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
    866866                                        noWiden(), symtab );
    867867                        } else if ( crnt2 != end2 ) {
    868868                                // try unifying empty tuple with ttype
    869                                 const ast::Type * t2 = *crnt2;
     869                                const ast::Type * t2 = (*crnt2)->get_type();
    870870                                if ( ! Tuples::isTtype( t2 ) ) return false;
    871871                                return unifyExact(
    872                                         tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
     872                                        tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
    873873                                        noWiden(), symtab );
    874874                        }
     
    877877                }
    878878
    879                 static bool unifyTypeList(
    880                         const std::vector< ast::ptr< ast::Type > > & list1,
    881                         const std::vector< ast::ptr< ast::Type > > & list2,
     879                static bool unifyDeclList(
     880                        const std::vector< ast::ptr< ast::DeclWithType > > & list1,
     881                        const std::vector< ast::ptr< ast::DeclWithType > > & list2,
    882882                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    883883                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    884884                ) {
    885                         return unifyTypeList(
     885                        return unifyDeclList(
    886886                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    887887                                symtab );
     
    928928                        ) return;
    929929
    930                         if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
    931                         if ( ! unifyTypeList(
     930                        if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
     931                        if ( ! unifyDeclList(
    932932                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    933933
     
    12321232        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    12331233                if ( func->returns.empty() ) return new ast::VoidType{};
    1234                 if ( func->returns.size() == 1 ) return func->returns[0];
     1234                if ( func->returns.size() == 1 ) return func->returns[0]->get_type();
    12351235
    12361236                std::vector<ast::ptr<ast::Type>> tys;
    1237                 for ( const auto & decl : func->returns ) {
    1238                         tys.emplace_back( decl );
     1237                for ( const ast::DeclWithType * decl : func->returns ) {
     1238                        tys.emplace_back( decl->get_type() );
    12391239                }
    12401240                return new ast::TupleType{ std::move(tys) };
  • src/SymTab/Autogen.cc

    r223a633 r33c3ded  
    339339                } catch ( SemanticErrorException & ) {
    340340                        // okay if decl does not resolve - that means the function should not be generated
    341                         // delete dcl;
    342                         delete dcl->statements;
    343                         dcl->statements = nullptr;
    344                         dcl->isDeleted = true;
    345                         definitions.push_back( dcl );
    346                         indexer.addId( dcl );
     341                        delete dcl;
    347342                }
    348343        }
  • src/SymTab/Mangler.cc

    r223a633 r33c3ded  
    551551                        GuardValue( inFunctionType );
    552552                        inFunctionType = true;
    553                         if (functionType->returns.empty()) mangleName << Encoding::void_t;
    554                         else accept_each( functionType->returns, *visitor );
     553                        std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns );
     554                        if (returnTypes.empty()) mangleName << Encoding::void_t;
     555                        else accept_each( returnTypes, *visitor );
    555556                        mangleName << "_";
    556                         accept_each( functionType->params, *visitor );
     557                        std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
     558                        accept_each( paramTypes, *visitor );
    557559                        mangleName << "_";
    558560                }
  • src/SymTab/Validate.cc

    r223a633 r33c3ded  
    13841384        /// Replaces enum types by int, and function/array types in function parameter and return
    13851385        /// lists by appropriate pointers
    1386         /*
    13871386        struct EnumAndPointerDecay_new {
    13881387                const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
     
    14351434                }
    14361435        };
    1437         */
    14381436
    14391437        /// expand assertions from a trait instance, performing appropriate type variable substitutions
     
    18391837const ast::Type * validateType(
    18401838                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1841         // ast::Pass< EnumAndPointerDecay_new > epc;
     1839        ast::Pass< EnumAndPointerDecay_new > epc;
    18421840        ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    18431841        ast::Pass< ForallPointerDecay_new > fpd{ loc };
    18441842
    1845         return type->accept( lrt )->accept( fpd );
     1843        return type->accept( epc )->accept( lrt )->accept( fpd );
    18461844}
    18471845
  • src/SynTree/AggregateDecl.cc

    r223a633 r33c3ded  
    2121#include "Common/utility.h"      // for printAll, cloneAll, deleteAll
    2222#include "Declaration.h"         // for AggregateDecl, TypeDecl, Declaration
    23 #include "Expression.h"
    2423#include "Initializer.h"
    2524#include "LinkageSpec.h"         // for Spec, linkageName, Cforall
     
    8988const char * StructDecl::typeString() const { return aggrString( kind ); }
    9089
    91 StructInstType * StructDecl::makeInst( std::list< Expression * > const & new_parameters ) {
    92         std::list< Expression * > copy_parameters;
    93         cloneAll( new_parameters, copy_parameters );
    94         return makeInst( move( copy( copy_parameters ) ) );
    95 }
    96 
    97 StructInstType * StructDecl::makeInst( std::list< Expression * > && new_parameters ) {
    98         assert( parameters.size() == new_parameters.size() );
    99         StructInstType * type = new StructInstType( noQualifiers, this );
    100         type->parameters = std::move( new_parameters );
    101         return type;
    102 }
    103 
    10490const char * UnionDecl::typeString() const { return aggrString( Union ); }
    10591
  • src/SynTree/Declaration.h

    r223a633 r33c3ded  
    306306        bool is_thread   () { return kind == Thread   ; }
    307307
    308         // Make a type instance of this declaration.
    309         StructInstType * makeInst( std::list< Expression * > const & parameters );
    310         StructInstType * makeInst( std::list< Expression * > && parameters );
    311 
    312308        virtual StructDecl * clone() const override { return new StructDecl( *this ); }
    313309        virtual void accept( Visitor & v ) override { v.visit( this ); }
  • src/SynTree/TypeDecl.cc

    r223a633 r33c3ded  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Oct  8 18:18:55 2020
    13 // Update Count     : 22
     12// Last Modified On : Fri Dec 13 15:26:14 2019
     13// Update Count     : 21
    1414//
    1515
     
    2121#include "Type.h"            // for Type, Type::StorageClasses
    2222
    23 TypeDecl::TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init ) :
    24         Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
     23TypeDecl::TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init ) : Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
    2524}
    2625
  • src/Virtual/Tables.cc

    r223a633 r33c3ded  
    1414//
    1515
    16 #include <SynTree/Attribute.h>
    1716#include <SynTree/Declaration.h>
    1817#include <SynTree/Expression.h>
    19 #include <SynTree/Statement.h>
    2018#include <SynTree/Type.h>
    2119
     
    4038}
    4139
     40// Fuse base polymorphic declaration and forall arguments into a new type.
     41static StructInstType * vtableInstType(
     42                StructDecl * polyDecl, std::list< Expression * > && parameters ) {
     43        assert( parameters.size() == polyDecl->parameters.size() );
     44        StructInstType * type = new StructInstType(
     45                        Type::Qualifiers( /* Type::Const */ ), polyDecl );
     46        type->parameters = std::move( parameters );
     47        return type;
     48}
     49
    4250static ObjectDecl * makeVtableDeclaration(
    4351                StructInstType * type, Initializer * init ) {
     
    5866
    5967ObjectDecl * makeVtableForward( StructInstType * type ) {
    60         assert( type );
    6168        return makeVtableDeclaration( type, nullptr );
    6269}
    6370
     71ObjectDecl * makeVtableForward(
     72                StructDecl * polyDecl, std::list< Expression * > && parameters ) {
     73        return makeVtableForward( vtableInstType( polyDecl, std::move( parameters ) ) );
     74}
     75
    6476ObjectDecl * makeVtableInstance(
    65                 StructInstType * vtableType, Type * objectType, Initializer * init ) {
    66         assert( vtableType );
    67         assert( objectType );
     77                StructInstType * vtableType, Type * vobject_type, Initializer * init ) {
    6878        StructDecl * vtableStruct = vtableType->baseStruct;
    6979        // Build the initialization
     
    8292                                                new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
    8393                        } else if ( std::string( "size" ) == field->name ) {
    84                                 inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
     94                                inits.push_back( new SingleInit( new SizeofExpr( vobject_type->clone() ) ) );
    8595                        } else if ( std::string( "align" ) == field->name ) {
    86                                 inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
     96                                inits.push_back( new SingleInit( new AlignofExpr( vobject_type->clone() ) ) );
    8797                        } else {
    8898                                inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
     
    98108}
    99109
    100 namespace {
    101         std::string const functionName = "get_exception_vtable";
    102 }
    103 
    104 FunctionDecl * makeGetExceptionForward(
    105                 Type * vtableType, Type * exceptType ) {
    106         assert( vtableType );
    107         assert( exceptType );
    108         FunctionType * type = new FunctionType( noQualifiers, false );
    109         vtableType->tq.is_const = true;
    110         type->returnVals.push_back( new ObjectDecl(
    111                 "_retvalue",
    112                 noStorageClasses,
    113                 LinkageSpec::Cforall,
    114                 nullptr,
    115                 new ReferenceType( noQualifiers, vtableType ),
    116                 nullptr,
    117         { new Attribute("unused") }
    118         ) );
    119         type->parameters.push_back( new ObjectDecl(
    120                 "__unused",
    121                 noStorageClasses,
    122                 LinkageSpec::Cforall,
    123                 nullptr,
    124                 new PointerType( noQualifiers, exceptType ),
    125                 nullptr,
    126                 { new Attribute("unused") }
    127         ) );
    128         return new FunctionDecl(
    129                 functionName,
    130                 noStorageClasses,
    131                 LinkageSpec::Cforall,
    132                 type,
    133                 nullptr
    134         );
    135 }
    136 
    137 FunctionDecl * makeGetExceptionFunction(
    138                 ObjectDecl * vtableInstance, Type * exceptType ) {
    139         assert( vtableInstance );
    140         assert( exceptType );
    141         FunctionDecl * func = makeGetExceptionForward(
    142                 vtableInstance->type->clone(), exceptType );
    143         func->statements = new CompoundStmt( {
    144                 new ReturnStmt( new VariableExpr( vtableInstance ) ),
    145         } );
    146         return func;
     110ObjectDecl * makeVtableInstance(
     111                StructDecl * polyDecl, std::list< Expression * > && parameters,
     112                Type * vobject, Initializer * init ) {
     113        return makeVtableInstance(
     114                vtableInstType( polyDecl, std::move( parameters ) ), vobject, init );
    147115}
    148116
  • src/Virtual/Tables.h

    r223a633 r33c3ded  
    2727bool isVTableInstanceName( std::string const & name );
    2828
    29 ObjectDecl * makeVtableForward( StructInstType * vtableType );
    30 /* Create a forward declaration of a vtable of the given type.
    31  * vtableType node is consumed.
     29/// Converts exceptions into regular structures.
     30//void ( std::list< Declaration * > & translationUnit );
     31
     32ObjectDecl * makeVtableForward( StructInstType * );
     33ObjectDecl * makeVtableForward( StructDecl *, std::list< Expression * > && );
     34/* Create a forward definition of a vtable of the given type.
     35 *
     36 * Instead of the virtual table type you may provide the declaration and all
     37 * the forall parameters.
    3238 */
    3339
    34 ObjectDecl * makeVtableInstance( StructInstType * vtableType, Type * objectType,
    35         Initializer * init = nullptr );
     40ObjectDecl * makeVtableInstance( StructInstType *, Type *, Initializer * );
     41ObjectDecl * makeVtableInstance(
     42        StructDecl *, std::list< Expression * > &&, Type *, Initializer * );
    3643/* Create an initialized definition of a vtable.
    37  * vtableType and init (if provided) nodes are consumed.
    38  */
    39 
    40 // Some special code for how exceptions interact with virtual tables.
    41 FunctionDecl * makeGetExceptionForward( Type * vtableType, Type * exceptType );
    42 /* Create a forward declaration of the exception virtual function
    43  * linking the vtableType to the exceptType. Both nodes are consumed.
    44  */
    45 
    46 FunctionDecl * makeGetExceptionFunction(
    47         ObjectDecl * vtableInstance, Type * exceptType );
    48 /* Create the definition of the exception virtual function.
    49  * exceptType node is consumed.
     44 *
     45 * The parameters are the virtual table type (or the base declaration and the
     46 * forall parameters), the object type and optionally an initializer.
     47 *
     48 * Instead of the virtual table type you may provide the declaration and all
     49 * the forall parameters.
    5050 */
    5151
  • src/main.cc

    r223a633 r33c3ded  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Oct  8 18:17:46 2020
    13 // Update Count     : 637
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue May 19 12:03:00 2020
     13// Update Count     : 634
    1414//
    1515
     
    451451
    452452
    453 static const char optstring[] = ":c:ghlLmNnpdOAP:S:twW:D:";
     453static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
    454454
    455455enum { PreludeDir = 128 };
     
    478478
    479479static const char * description[] = {
    480         "diagnostic color: never, always, or auto.",            // -c
    481         "wait for gdb to attach",                                                       // -g
    482         "print help message",                                                           // -h
    483         "generate libcfa.c",                                                            // -l
    484         "generate line marks",                                                          // -L
    485         "do not replace main",                                                          // -m
    486         "do not generate line marks",                                           // -N
    487         "do not read prelude",                                                          // -n
     480        "diagnostic color: never, always, or auto.",          // -c
     481        "wait for gdb to attach",                             // -g
     482        "print help message",                                 // -h
     483        "generate libcfa.c",                                  // -l
     484        "generate line marks",                                // -L
     485        "do not replace main",                                // -m
     486        "do not generate line marks",                         // -N
     487        "do not read prelude",                                // -n
    488488        "generate prototypes for prelude functions",            // -p
    489         "only print deterministic output",                  // -d
    490         "Use the old-ast",                                                                      // -O
    491         "Use the new-ast",                                                                      // -A
    492         "print",                                                                                        // -P
     489        "don't print output that isn't deterministic",        // -d
     490        "Use the old-ast",                                    // -O
     491        "Use the new-ast",                                    // -A
     492        "print",                                              // -P
    493493        "<directory> prelude directory for debug/nodebug",      // no flag
    494494        "<option-list> enable profiling information:\n          counters,heap,time,all,none", // -S
    495         "building cfa standard lib",                                            // -t
    496         "",                                                                                                     // -w
    497         "",                                                                                                     // -W
    498         "",                                                                                                     // -D
     495        "building cfa standard lib",                          // -t
     496        "",                                                   // -w
     497        "",                                                   // -W
     498        "",                                                   // -D
    499499}; // description
    500500
  • tests/.expect/array.txt

    r223a633 r33c3ded  
    1 array.cfa: In function '_X4mainFi___1':
    2 array.cfa:55:9: note: #pragma message: Compiled
  • tests/.expect/cast.txt

    r223a633 r33c3ded  
    1 cast.cfa: In function '_X4mainFi_iPPKc__1':
    2 cast.cfa:18:9: note: #pragma message: Compiled
  • tests/.expect/enum.txt

    r223a633 r33c3ded  
    1 done
  • tests/.expect/expression.txt

    r223a633 r33c3ded  
    1 expression.cfa: In function '_X4mainFi___1':
    2 expression.cfa:89:9: note: #pragma message: Compiled
  • tests/.expect/forall.txt

    r223a633 r33c3ded  
    1 forall.cfa: In function '_X4mainFi___1':
    2 forall.cfa:218:9: note: #pragma message: Compiled
  • tests/.expect/heap.txt

    r223a633 r33c3ded  
    1 done
  • tests/.expect/identFuncDeclarator.txt

    r223a633 r33c3ded  
    1 identFuncDeclarator.cfa: In function '_X4mainFi___1':
    2 identFuncDeclarator.cfa:116:9: note: #pragma message: Compiled
  • tests/.expect/identParamDeclarator.txt

    r223a633 r33c3ded  
    1 done
  • tests/.expect/init1.txt

    r223a633 r33c3ded  
    1 init1.cfa: In function '_X4mainFi___1':
    2 init1.cfa:136:9: note: #pragma message: Compiled
     1error: No reasonable alternatives for expression Untyped Init Expression
     2  Name: rx  InitAlternative: reference to signed int
     3error: No reasonable alternatives for expression Untyped Init Expression
     4  Name: px  InitAlternative: pointer to signed int
     5error: No reasonable alternatives for expression Untyped Init Expression
     6  Name: crx  InitAlternative: reference to float
     7error: No reasonable alternatives for expression Untyped Init Expression
     8  Name: cpx  InitAlternative: pointer to float
     9init1.cfa:94:1 error: No reasonable alternatives for expression Generated Cast of:
     10  Name: rx
     11... to:
     12  reference to signed int
     13init1.cfa:97:1 error: No reasonable alternatives for expression Applying untyped:
     14  Name: ?{}
     15...to:
     16  Generated Cast of:
     17    Variable Expression: _retval_f_py: pointer to signed int
     18  ... to:
     19    reference to pointer to signed int
     20  Name: px
     21
     22init1.cfa:104:1 error: No reasonable alternatives for expression Generated Cast of:
     23  Name: crx
     24... to:
     25  reference to float
     26init1.cfa:107:1 error: No reasonable alternatives for expression Applying untyped:
     27  Name: ?{}
     28...to:
     29  Generated Cast of:
     30    Variable Expression: _retval_f_py2: pointer to float
     31  ... to:
     32    reference to pointer to float
     33  Name: cpx
     34
     35init1.cfa:114:1 error: No reasonable alternatives for expression Generated Cast of:
     36  Name: s
     37... to:
     38  reference to instance of type T (not function type)
     39init1.cfa:118:1 error: No reasonable alternatives for expression Applying untyped:
     40  Name: ?{}
     41...to:
     42  Generated Cast of:
     43    Variable Expression: _retval_anycvt: pointer to instance of type T (not function type)
     44  ... to:
     45    reference to pointer to instance of type T (not function type)
     46  Name: s
     47
  • tests/.expect/labelledExit.txt

    r223a633 r33c3ded  
    1 labelledExit.cfa: In function '_X4mainFi_iPPKc__1':
    2 labelledExit.cfa:183:9: note: #pragma message: Compiled
  • tests/.expect/limits.txt

    r223a633 r33c3ded  
    1 limits.cfa: In function '_X4mainFi_iPPKc__1':
    2 limits.cfa:154:9: note: #pragma message: Compiled
  • tests/.expect/maybe.txt

    r223a633 r33c3ded  
    1 done
  • tests/.expect/nested-types.txt

    r223a633 r33c3ded  
    1 nested-types.cfa: In function '_X4mainFi___1':
    2 nested-types.cfa:102:9: note: #pragma message: Compiled
  • tests/.expect/numericConstants.txt

    r223a633 r33c3ded  
    1 numericConstants.cfa: In function '_X4mainFi___1':
    2 numericConstants.cfa:68:9: note: #pragma message: Compiled
  • tests/.expect/operators.txt

    r223a633 r33c3ded  
    1 done
  • tests/.expect/result.txt

    r223a633 r33c3ded  
    1 done
  • tests/.expect/stdincludes.txt

    r223a633 r33c3ded  
    1 stdincludes.cfa: In function '_X4mainFi___1':
    2 stdincludes.cfa:52:9: note: #pragma message: Compiled
  • tests/.expect/switch.txt

    r223a633 r33c3ded  
    1 switch.cfa: In function '_X4mainFi___1':
    2 switch.cfa:105:9: note: #pragma message: Compiled
  • tests/.expect/typedefRedef-ERR1.txt

    r223a633 r33c3ded  
    11typedefRedef.cfa:4:1 error: Cannot redefine typedef: Foo
    2 typedefRedef.cfa:59:1 error: Cannot redefine typedef: ARR
     2typedefRedef.cfa:60:1 error: Cannot redefine typedef: ARR
  • tests/.expect/typedefRedef.txt

    r223a633 r33c3ded  
    1 typedefRedef.cfa: In function '_X4mainFi___1':
    2 typedefRedef.cfa:71:9: note: #pragma message: Compiled
  • tests/.expect/typeof.txt

    r223a633 r33c3ded  
    1 done
  • tests/.expect/variableDeclarator.txt

    r223a633 r33c3ded  
    1 variableDeclarator.cfa: In function '_X4mainFi_iPPKc__1':
    2 variableDeclarator.cfa:182:9: note: #pragma message: Compiled
  • tests/.expect/voidPtr.txt

    r223a633 r33c3ded  
    1 done
  • tests/Makefile.am

    r223a633 r33c3ded  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Fri Oct  9 23:13:07 2020
    14 ## Update Count     : 86
     13## Last Modified On : Tue Nov 20 11:18:51 2018
     14## Update Count     : 68
    1515###############################################################################
    1616
     
    4040        -fdebug-prefix-map=$(abspath ${abs_srcdir})= \
    4141        -fdebug-prefix-map=/tmp= \
    42         -fno-diagnostics-show-caret \
    4342        -g \
    4443        -Wall \
     
    5352
    5453# adjust CC to current flags
    55 CC = LC_ALL=C $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
     54CC = $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
    5655CFACC = $(CC)
    5756
     
    134133        $(CFACOMPILETEST) -CFA -XCFA -p -c -fsyntax-only -o $(abspath ${@})
    135134
     135# Use for tests where the make command is expected to succeed but the expected.txt should be compared to stderr
     136EXPECT_STDERR = builtins/sync warnings/self-assignment
     137$(EXPECT_STDERR): % : %.cfa $(CFACCBIN)
     138        $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})
     139
    136140#------------------------------------------------------------------------------
    137141# CUSTOM TARGET
    138142#------------------------------------------------------------------------------
    139 # tests that just validate syntax and compiler output should be compared to stderr
    140 CFACOMPILE_SYNTAX = $(CFACOMPILETEST) -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o $(abspath ${@})
    141 
    142 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator forall \
    143         init1 limits nested-types stdincludes cast labelledExit array builtins/sync warnings/self-assignment
    144 $(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN)
    145         $(CFACOMPILE_SYNTAX)
    146         $(if $(test), cp $(test) $(abspath ${@}), )
     143# tests that just validate syntax
     144expression : expression.cfa $(CFACCBIN)
     145        $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})
    147146
    148147# expected failures
    149 # use custom target since they require a custom define *and* have a name that doesn't match the file
     148# use custom target since they require a custom define and custom dependencies
    150149alloc-ERROR : alloc.cfa $(CFACCBIN)
    151         $(CFACOMPILE_SYNTAX) -DERR1
    152         -cp $(test) $(abspath ${@})
    153 
    154 init1-ERROR : init1.cfa $(CFACCBIN)
    155         $(CFACOMPILE_SYNTAX) -DERR1
    156         -cp $(test) $(abspath ${@})
     150        $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
    157151
    158152typedefRedef-ERR1 : typedefRedef.cfa $(CFACCBIN)
    159         $(CFACOMPILE_SYNTAX) -DERR1
    160         -cp $(test) $(abspath ${@})
     153        $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
    161154
    162155nested-types-ERR1 : nested-types.cfa $(CFACCBIN)
    163         $(CFACOMPILE_SYNTAX) -DERR1
    164         -cp $(test) $(abspath ${@})
     156        $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
    165157
    166158nested-types-ERR2 : nested-types.cfa $(CFACCBIN)
    167         $(CFACOMPILE_SYNTAX) -DERR2
    168         -cp $(test) $(abspath ${@})
     159        $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@})
    169160
    170161raii/memberCtors-ERR1 : raii/memberCtors.cfa $(CFACCBIN)
    171         $(CFACOMPILE_SYNTAX) -DERR1
    172         -cp $(test) $(abspath ${@})
     162        $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
    173163
    174164raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa $(CFACCBIN)
    175         $(CFACOMPILE_SYNTAX) -DERR1
    176         -cp $(test) $(abspath ${@})
     165        $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
    177166
    178167raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa $(CFACCBIN)
    179         $(CFACOMPILE_SYNTAX) -DERR1
    180         -cp $(test) $(abspath ${@})
     168        $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
    181169
    182170raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa $(CFACCBIN)
    183         $(CFACOMPILE_SYNTAX) -DERR2
    184         -cp $(test) $(abspath ${@})
     171        $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@})
    185172
    186173# Exception Tests
  • tests/alloc.cfa

    r223a633 r33c3ded  
    1010// Created On       : Wed Feb  3 07:56:22 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct  9 23:03:11 2020
    13 // Update Count     : 431
     12// Last Modified On : Fri Aug 14 16:59:59 2020
     13// Update Count     : 430
    1414//
    1515
     
    362362        ip = memset( stp, 10 );
    363363        ip = memcpy( &st1, &st );
    364 #endif // ERR1
     364#endif
    365365} // main
    366366
  • tests/array.cfa

    r223a633 r33c3ded  
    1 //                               -*- Mode: C -*-
    2 //
     1//                               -*- Mode: C -*- 
     2// 
    33// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
    44//
    55// The contents of this file are covered under the licence agreement in the
    66// file "LICENCE" distributed with Cforall.
    7 //
     7// 
    88// array.cfa -- test array declarations
    9 //
     9// 
    1010// Author           : Peter A. Buhr
    1111// Created On       : Tue Feb 19 21:18:06 2019
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Sun Sep 27 09:05:40 2020
    14 // Update Count     : 4
    15 //
     13// Last Modified On : Tue Feb 19 21:18:46 2019
     14// Update Count     : 1
     15// 
    1616
    17 int a1[0];
     17int a1[];
    1818//int a2[*];
    1919//double a4[3.0];
    2020
    21 int m1[0][3];
     21int m1[][3];
    2222//int m2[*][*];
    2323int m4[3][3];
     
    4949}
    5050
    51 int main() {
    52         #if !defined(NO_COMPILED_PRAGMA)
    53                 #pragma message( "Compiled" )   // force non-empty .expect file
    54         #endif
    55 }
     51int main() {}
    5652
    5753// Local Variables: //
  • tests/builtins/.expect/sync.txt

    r223a633 r33c3ded  
    1 builtins/sync.cfa: In function '_X4mainFi___1':
    2 builtins/sync.cfa:358:9: note: #pragma message: Compiled
  • tests/builtins/sync.cfa

    r223a633 r33c3ded  
    6666        #if defined(__SIZEOF_INT128__)
    6767        { __int128 ret; ret = __sync_fetch_and_nand(vplll, vlll); }
     68        { __int128 ret; ret = __sync_fetch_and_nand_16(vplll, vlll); }
    6869        #endif
    6970
     
    354355
    355356int main() {
    356         #pragma message( "Compiled" )                   // force non-empty .expect file
     357        return 0;
    357358}
  • tests/cast.cfa

    r223a633 r33c3ded  
    1313
    1414//Dummy main
    15 int main( int argc, char const * argv[] ) {
    16         #pragma message( "Compiled" )                   // force non-empty .expect file
     15int main(int argc, char const *argv[])
     16{
     17        return 0;
    1718}
  • tests/concurrent/.expect/cluster.txt

    r223a633 r33c3ded  
    1 done
  • tests/concurrent/cluster.cfa

    r223a633 r33c3ded  
    3232                }
    3333        }
    34         printf( "done\n" );                             // non-empty .expect file
     34        return 0;
    3535}
  • tests/concurrent/examples/.expect/datingService.txt

    r223a633 r33c3ded  
    1 done
  • tests/concurrent/examples/datingService.cfa

    r223a633 r33c3ded  
    1010// Created On       : Mon Oct 30 12:56:20 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 15:42:25 2020
    13 // Update Count     : 40
     12// Last Modified On : Fri Jun 21 11:32:34 2019
     13// Update Count     : 38
    1414//
    1515
     
    108108                if ( girlck[ boyck[i] ] != boyck[ girlck[i] ] ) abort();
    109109        } // for
    110 
    111         printf( "done\n" );                                                                     // non-empty .expect file
    112110} // main
    113111
  • tests/concurrent/futures/.expect/basic.txt

    r223a633 r33c3ded  
    1 done
  • tests/concurrent/futures/basic.cfa

    r223a633 r33c3ded  
    9191                }
    9292        }
    93         printf( "done\n" );                             // non-empty .expect file
    94 
    9593}
  • tests/concurrent/park/.expect/force_preempt.txt

    r223a633 r33c3ded  
    1 done
  • tests/concurrent/park/.expect/start_parked.txt

    r223a633 r33c3ded  
    1 done
  • tests/concurrent/park/contention.cfa

    r223a633 r33c3ded  
    2121                if(blocked[idx]) {
    2222                        Thread * thrd = __atomic_exchange_n(&blocked[idx], 0p, __ATOMIC_SEQ_CST);
    23                         unpark( *thrd );
     23                        unpark( *thrd __cfaabi_dbg_ctx2 );
    2424                } else {
    2525                        Thread * thrd = __atomic_exchange_n(&blocked[idx], &this, __ATOMIC_SEQ_CST);
    26                         unpark( *thrd );
    27                         park();
     26                        unpark( *thrd __cfaabi_dbg_ctx2 );
     27                        park( __cfaabi_dbg_ctx );
    2828                }
    2929        }
     
    4141                        int idx = myrand() % blocked_size;
    4242                        Thread * thrd = __atomic_exchange_n(&blocked[idx], 0p, __ATOMIC_SEQ_CST);
    43                         unpark( *thrd );
     43                        unpark( *thrd __cfaabi_dbg_ctx2 );
    4444                        yield( myrand() % 20 );
    4545                }
  • tests/concurrent/park/force_preempt.cfa

    r223a633 r33c3ded  
    3030
    3131                // Unpark this thread, don't force a yield
    32                 unpark( this );
     32                unpark( this __cfaabi_dbg_ctx2 );
    3333                assert(mask == 0xCAFEBABA);
    3434
     
    4343                // Park this thread,
    4444                assert(mask == (id_hash ^ 0xCAFEBABA));
    45                 park();
     45                park( __cfaabi_dbg_ctx );
    4646                assert(mask == (id_hash ^ 0xCAFEBABA));
    4747
     
    5757                Waiter waiters[5];
    5858        }
    59         printf( "done\n" );                             // non-empty .expect file
    6059}
  • tests/concurrent/park/start_parked.cfa

    r223a633 r33c3ded  
    33thread Parker {};
    44void main( Parker & ) {
    5         park();
     5      park( __cfaabi_dbg_ctx );
    66}
    77
    88int main() {
    9         for(1000) {
    10                 Parker parker;
    11                 unpark( parker );
    12         }
    13         printf( "done\n" );                                                                     // non-empty .expect file
     9      for(1000) {
     10            Parker parker;
     11            unpark( parker __cfaabi_dbg_ctx2 );
     12      }
    1413}
  • tests/enum.cfa

    r223a633 r33c3ded  
    2626//Dummy main
    2727int main(int argc, char const *argv[]) {
    28         printf( "done\n" );                             // non-empty .expect file
    2928}
  • tests/errors/.expect/completeType.x64.txt

    r223a633 r33c3ded  
    132132?=?: pointer to function
    133133        ... with parameters
    134           reference to instance of type _110_0_T (not function type)
    135           instance of type _110_0_T (not function type)
     134          reference to instance of type _109_0_T (not function type)
     135          instance of type _109_0_T (not function type)
    136136        ... returning
    137           _retval__operator_assign: instance of type _110_0_T (not function type)
     137          _retval__operator_assign: instance of type _109_0_T (not function type)
    138138          ... with attributes:
    139139            Attribute with name: unused
  • tests/errors/.expect/completeType.x86.txt

    r223a633 r33c3ded  
    132132?=?: pointer to function
    133133        ... with parameters
    134           reference to instance of type _109_0_T (not function type)
    135           instance of type _109_0_T (not function type)
     134          reference to instance of type _108_0_T (not function type)
     135          instance of type _108_0_T (not function type)
    136136        ... returning
    137           _retval__operator_assign: instance of type _109_0_T (not function type)
     137          _retval__operator_assign: instance of type _108_0_T (not function type)
    138138          ... with attributes:
    139139            Attribute with name: unused
  • tests/exceptions/.expect/virtual-cast.txt

    r223a633 r33c3ded  
    1 done
  • tests/exceptions/.expect/virtual-poly.txt

    r223a633 r33c3ded  
    1 done
  • tests/exceptions/defaults.cfa

    r223a633 r33c3ded  
    5555
    5656void unhandled_test(void) {
    57         forall(dtype T, dtype V | is_exception(T, V))
     57        forall(dtype T | is_exception(T))
    5858        void defaultTerminationHandler(T &) {
    5959                throw (unhandled_exception){};
  • tests/exceptions/virtual-cast.cfa

    r223a633 r33c3ded  
    7474        free(tri);
    7575        free(top);
    76         printf( "done\n" );                             // non-empty .expect file
    7776}
  • tests/exceptions/virtual-poly.cfa

    r223a633 r33c3ded  
    7777        mono_poly_test();
    7878        poly_poly_test();
    79         printf( "done\n" );                             // non-empty .expect file
    8079}
  • tests/expression.cfa

    r223a633 r33c3ded  
    88
    99int main() {
    10         int a[3] = { 0, 0, 0 };
    11         S s = { 3 }, * ps = &s;
    12         [int] t = { 3 };
    13         * [int] pt = &t;
    14         int i = 1, j = 2;
     10    int a[3] = { 0, 0, 0 };
     11    S s = { 3 }, * ps = &s;
     12    [int] t = { 3 };
     13    * [int] pt = &t;
     14    int i = 1, j = 2;
    1515
    16         // operators
     16    // operators
    1717
    18         !i;
    19         ~i;
    20         +i;
    21         -i;
    22         *ps;
    23         ++ps;
    24         --ps;
    25         ps++;
    26         ps--;
     18    !i;
     19    ~i;
     20    +i;
     21    -i;
     22    *ps;
     23    ++ps;
     24    --ps;
     25    ps++;
     26    ps--;
    2727
    28         i + j;
    29         i - j;
    30         i * j;
     28    i + j;
     29    i - j;
     30    i * j;
    3131
    32         i / j;
    33         i % j;
    34         i ^ j;
    35         i & j;
    36         i | j;
    37         i < j;
    38         i > j;
    39         i = j;
     32    i / j;
     33    i % j;
     34    i ^ j;
     35    i & j;
     36    i | j;
     37    i < j;
     38    i > j;
     39    i = j;
    4040
    41         i == j;
    42         i != j;
    43         i << j;
    44         i >> j;
    45         i <= j;
    46         i >= j;
    47         i && j;
    48         i || j;
    49         ps->i;
     41    i == j;
     42    i != j;
     43    i << j;
     44    i >> j;
     45    i <= j;
     46    i >= j;
     47    i && j;
     48    i || j;
     49    ps->i;
    5050
    51         i *= j;
    52         i /= j;
    53         i %= j;
    54         i += j;
    55         i -= j;
    56         i &= j;
    57         i |= j;
    58         i ^= j;
    59         i <<= j;
    60         i >>= j;
     51    i *= j;
     52    i /= j;
     53    i %= j;
     54    i += j;
     55    i -= j;
     56    i &= j;
     57    i |= j;
     58    i ^= j;
     59    i <<= j;
     60    i >>= j;
    6161
    62         i ? i : j;
     62    i ? i : j;
    6363
    64         // postfix function call
     64    // postfix function call
    6565
    66         (3 + 4)`mary;
    67         ({3 + 4;})`mary;
    68         [3, 4]`mary;
    69         3`mary;
    70         a[0]`mary;
    71         a[0]`mary`mary;
    72         s{0}`mary;
    73         a[3]`jane++;
    74         jack(3)`mary;
    75         s.i`mary;
    76         t.0`mary;
    77         s.[i]`mary;
    78         ps->i`mary;
    79         pt->0`mary;
    80         ps->[i]`mary;
    81         i++`mary;
    82         i--`mary;
    83         (S){2}`mary;
    84         (S)@{2}`mary;
    85 
    86         #if !defined(NO_COMPILED_PRAGMA)
    87                 #pragma message( "Compiled" )   // force non-empty .expect file
    88         #endif
     66    (3 + 4)`mary;
     67    ({3 + 4;})`mary;
     68    [3, 4]`mary;
     69    3`mary;
     70    a[0]`mary;
     71    a[0]`mary`mary;
     72    s{0}`mary;
     73    a[3]`jane++;
     74    jack(3)`mary;
     75    s.i`mary;
     76    t.0`mary;
     77    s.[i]`mary;
     78    ps->i`mary;
     79    pt->0`mary;
     80    ps->[i]`mary;
     81    i++`mary;
     82    i--`mary;
     83    (S){2}`mary;
     84    (S)@{2}`mary;
    8985} // main
  • tests/forall.cfa

    r223a633 r33c3ded  
    1010// Created On       : Wed May  9 08:48:15 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 08:43:20 2020
    13 // Update Count     : 35
     12// Last Modified On : Tue Mar 19 08:29:38 2019
     13// Update Count     : 32
    1414//
    1515
     
    158158}
    159159forall( otype T ) inline static {
    160         int RT9( T ) { T t; return 3; }
     160        int RT9( T ) { T t; }
    161161}
    162162
     
    213213// w3 g3;
    214214
    215 int main( void ) {
    216         #pragma message( "Compiled" )                   // force non-empty .expect file
    217 }
     215int main( void ) {}
    218216
    219217// Local Variables: //
  • tests/heap.cfa

    r223a633 r33c3ded  
    1010// Created On       : Tue Nov  6 17:54:56 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Sep 25 15:21:52 2020
    13 // Update Count     : 73
     12// Last Modified On : Mon Sep  7 18:37:41 2020
     13// Update Count     : 72
    1414//
    1515
     
    485485        // checkFreeOn();
    486486        // malloc_stats();
    487         printf( "done\n" );                                                                     // non-empty .expect file
    488487}
    489488
  • tests/identFuncDeclarator.cfa

    r223a633 r33c3ded  
    1010// Created On       : Wed Aug 17 08:36:34 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 08:20:46 2020
    13 // Update Count     : 5
     12// Last Modified On : Tue Nov  6 17:56:33 2018
     13// Update Count     : 3
    1414//
    1515
     
    111111        int (* (* const f80)(int))();
    112112        int (* const(* const f81)(int))();
    113 
    114         #pragma message( "Compiled" )                   // force non-empty .expect file
    115113}
    116114
  • tests/identParamDeclarator.cfa

    r223a633 r33c3ded  
    1010// Created On       : Wed Aug 17 08:37:56 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Sep 25 14:31:08 2020
    13 // Update Count     : 4
     12// Last Modified On : Tue Nov  6 17:56:44 2018
     13// Update Count     : 3
    1414//
    1515
     
    158158
    159159int main( int argc, char const *argv[] ) {                              // dummy main
    160         printf( "done\n" );                                                                     // non-empty .expect file
     160        return 0;
    161161}
    162162
  • tests/init1.cfa

    r223a633 r33c3ded  
    99// Author           : Michael Brooks
    1010// Created On       : Thu Jul 16 22:00:00 2020
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Oct 11 10:26:50 2020
    13 // Update Count     : 8
     11// Last Modified By : Michael Brooks
     12// Last Modified On : Thu Jul 16 22:00:00 2020
     13// Update Count     : 1
    1414//
    1515
     
    4141    const float * cpx2 = cpx;
    4242
    43     // FIX ME: Code gen not producing correct cast.
    44 #pragma GCC diagnostic push
    45 #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
    46     int (* fp)( int ) = 0p;
    47     fp = 0p;
    48 #pragma GCC diagnostic pop
    49 
    5043    //
    5144    // unsound initializations
    5245    //
    5346
    54     #ifdef ERR1
    5547    // mismatched referenced type
    5648    int & ry = rx;
     
    6052    float & ry2 = crx;
    6153    float * py2 = cpx;
    62     #endif // ERR1
    6354}
    6455
     
    9990//
    10091
    101 #ifdef ERR1
    10292int & f_ry() {
    10393    float & rx = *0p;
     
    129119    return s;               // mismatched referenced type
    130120}
    131 #endif // ERR1
    132 
    133 int main() {
    134     #pragma message( "Compiled" )                       // force non-empty .expect file
    135 }
  • tests/labelledExit.cfa

    r223a633 r33c3ded  
    1010// Created On       : Wed Aug 10 07:29:39 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 09:01:34 2020
    13 // Update Count     : 12
     12// Last Modified On : Wed Feb  5 16:49:48 2020
     13// Update Count     : 9
    1414//
    1515
     
    179179
    180180int main( int argc, char const *argv[] ) {
    181         #pragma message( "Compiled" )                                           // force non-empty .expect file
     181        /* code */
    182182}
    183183
  • tests/limits.cfa

    r223a633 r33c3ded  
    1010// Created On       : Tue May 10 20:44:20 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 08:45:43 2020
    13 // Update Count     : 10
     12// Last Modified On : Tue Nov  6 17:57:55 2018
     13// Update Count     : 8
    1414//
    15 
    16 // Note: For testing the ability to load the constants defined in libcfa/src/limits.cfa,
    17 // see discussion in test const-init.
    1815
    1916#include <limits.hfa>
     
    150147
    151148int main(int argc, char const *argv[]) {
    152         #pragma message( "Compiled" )                                           // force non-empty .expect file
     149        //DUMMY
     150        return 0;
    153151}
    154152
  • tests/maybe.cfa

    r223a633 r33c3ded  
    1010// Created On       : Thr May 25 16:02:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Sep 25 15:13:28 2020
    13 // Update Count     : 2
     12// Last Modified On : Thu Jul 20 15:24:07 2017
     13// Update Count     : 1
    1414//
    1515
     
    6565        //checkNamedConstructors();
    6666        checkSetters();
    67         printf( "done\n" );                             // non-empty .expect file
    6867}
  • tests/nested-types.cfa

    r223a633 r33c3ded  
    1010// Created On       : Mon Jul 9 10:20:03 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 08:48:59 2020
    13 // Update Count     : 6
     12// Last Modified On : Wed Feb 12 18:21:15 2020
     13// Update Count     : 3
    1414//
    1515
    1616typedef int N;
    1717struct A {
    18         forall(otype T)
    19         struct N {
    20                 T x;
    21         };
     18  forall(otype T)
     19  struct N {
     20    T x;
     21  };
    2222};
    2323
    2424struct S {
    25         struct T {
    26                 int i;
    27                 typedef int Bar;
    28         };
    29         T x;
     25  struct T {
     26    int i;
     27    typedef int Bar;
     28  };
     29  T x;
    3030
    31         // struct U;
    32         typedef T Bar;
    33         typedef int Baz;
     31  // struct U;
     32  typedef T Bar;
     33  typedef int Baz;
    3434};
    3535
     
    6565
    6666int main() {
    67         // access nested struct
    68         S.T x;
     67  // access nested struct
     68  S.T x;
    6969
    70         {
    71                 struct S {
    72                   int i;
    73                   struct Z {
    74                     double d;
    75                   };
    76                 };
     70  {
     71    struct S {
     72      int i;
     73      struct Z {
     74        double d;
     75      };
     76    };
    7777
    78                 S.Z z;                                                                                  // gets local S
    79                 .S.T y;                                                                                 // lookup at global scope only
     78    S.Z z;   // gets local S
     79    .S.T y;  // lookup at global scope only
    8080
    81                 const volatile .S.T q;
     81    const volatile .S.T q;
    8282#if ERR1
    83                 T err1;                                                                                 // error: no T in scope
     83    T err1;           // error: no T in scope
    8484#endif
    8585#if ERR2
    86                 .Z err2;                                                                                // error: no Z in global scope
    87                 .S.Baz.Bar err3;                                                                // error: .S.Baz => int, int is not aggregate and should not appear left of the dot
    88                 .S.Z err4;                                                                              // error: no Z in global S
     86    .Z err2;          // error: no Z in global scope
     87    .S.Baz.Bar err3;  // error: .S.Baz => int, int is not aggregate and should not appear left of the dot
     88    .S.Z err4;        // error: no Z in global S
    8989#endif
    90         }
     90  }
    9191
    92         // U.S un;
     92  // U.S un;
    9393
    94         S.Bar y;
    95         S.Baz x;
    96         S.T.Bar z;
     94  S.Bar y;
     95  S.Baz x;
     96  S.T.Bar z;
    9797
    98         // A.N(int) x;  // xxx - should not be an error, but currently is.
    99 
    100         #pragma message( "Compiled" )                   // force non-empty .expect file
     98  // A.N(int) x;  // xxx - should not be an error, but currently is.
    10199}
    102100
  • tests/numericConstants.cfa

    r223a633 r33c3ded  
    1010// Created On       : Wed May 24 22:10:36 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 07:55:22 2020
    13 // Update Count     : 7
     12// Last Modified On : Tue Feb  5 08:58:16 2019
     13// Update Count     : 5
    1414//
    1515
     
    6363        0x_ff.ffp0;                                     // hex real
    6464        0x_1.ffff_ffff_p_128_l;
    65 
    66         #pragma message( "Compiled" )   // force non-empty .expect file
    6765} // main
    6866
  • tests/operators.cfa

    r223a633 r33c3ded  
    3131int main(int argc, char const *argv[]) {
    3232        /* code */
    33         printf( "done\n" );                             // non-empty .expect file
     33        return 0;
    3434}
    3535
  • tests/pybin/tools.py

    r223a633 r33c3ded  
    8888                raise
    8989
    90 def is_empty(fname):
    91         if not os.path.isfile(fname):
    92                 return True
    93 
    94         if os.stat(fname).st_size == 0:
    95                 return True
    96 
    97         return False
    98 
    9990def is_ascii(fname):
    10091        if settings.dry_run:
    10192                print("is_ascii: %s" % fname)
    102                 return (True, "")
     93                return True
    10394
    10495        if not os.path.isfile(fname):
    105                 return (False, "No file")
    106 
    107         code, out = sh("file", fname, output_file=subprocess.PIPE)
     96                return False
     97
     98        code, out = sh("file %s" % fname, output_file=subprocess.PIPE)
    10899        if code != 0:
    109                 return (False, "'file EXPECT' failed with code {}".format(code))
     100                return False
    110101
    111102        match = re.search(".*: (.*)", out)
    112103
    113104        if not match:
    114                 return (False, "Unreadable file type: '{}'".format(out))
    115 
    116         if "ASCII text" in match.group(1):
    117                 return (True, "")
    118 
    119         return (False, "File type should be 'ASCII text', was '{}'".format(match.group(1)))
     105                return False
     106
     107        return match.group(1).startswith("ASCII text")
    120108
    121109def is_exe(fname):
  • tests/raii/.expect/ctor-autogen.txt

    r223a633 r33c3ded  
    1 done
  • tests/raii/.expect/init_once.txt

    r223a633 r33c3ded  
    1 done
  • tests/raii/ctor-autogen.cfa

    r223a633 r33c3ded  
    151151        identity(gcs);
    152152        identity(gcu);
    153         printf( "done\n" );                             // non-empty .expect file
    154153}
  • tests/raii/init_once.cfa

    r223a633 r33c3ded  
    1010// Created On       : Tue Jun 14 15:43:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Sep 25 15:36:39 2020
    13 // Update Count     : 5
     12// Last Modified On : Fri Mar 22 13:41:26 2019
     13// Update Count     : 4
    1414//
    1515
     
    188188                static_variable();
    189189        }
    190         printf( "done\n" );                                                                     // non-empty .expect file
    191190}
    192191
  • tests/result.cfa

    r223a633 r33c3ded  
    1010// Created On       : Thr May 25 16:50:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Sep 25 15:22:59 2020
    13 // Update Count     : 2
     12// Last Modified On : Thu Jul 20 15:24:12 2017
     13// Update Count     : 1
    1414//
    1515
     
    6666        checkGetters();
    6767        checkSetters();
    68         printf( "done\n" );                             // non-empty .expect file
    6968}
  • tests/stdincludes.cfa

    r223a633 r33c3ded  
    1010// Created On       : Tue Aug 29 08:26:14 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 08:51:38 2020
    13 // Update Count     : 8
     12// Last Modified On : Tue Nov  6 18:00:53 2018
     13// Update Count     : 6
    1414//
    1515
     
    4747#include <wctype.h>
    4848
    49 int main() {
    50         #pragma message( "Compiled" )                   // force non-empty .expect file
    51 }
     49int main() {}
    5250
    5351// Local Variables: //
  • tests/switch.cfa

    r223a633 r33c3ded  
    1010// Created On       : Tue Jul 12 06:50:22 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 08:35:02 2020
    13 // Update Count     : 43
     12// Last Modified On : Tue Nov  6 18:01:34 2018
     13// Update Count     : 37
    1414//
    1515
     
    100100                j = 5;
    101101        } // choose
    102 
    103         #pragma message( "Compiled" )                                           // force non-empty .expect file
    104102} // main
    105103
  • tests/test.py

    r223a633 r33c3ded  
    173173        test.prepare()
    174174
    175         # ----------
    176         # MAKE
    177         # ----------
    178175        # build, skipping to next test on error
    179176        with Timed() as comp_dur:
    180177                make_ret, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file )
    181178
    182         # ----------
    183         # RUN
    184         # ----------
     179        run_dur = None
    185180        # run everything in a temp directory to make sure core file are handled properly
    186         run_dur = None
    187181        with tempdir():
    188182                # if the make command succeeds continue otherwise skip to diff
     
    262256        make('clean', output_file=subprocess.DEVNULL, error=subprocess.DEVNULL)
    263257
    264         # create the executor for our jobs
    265         pool = multiprocessing.Pool(jobs)
     258        # since python prints stacks by default on a interrupt, redo the interrupt handling to be silent
     259        def worker_init():
     260                def sig_int(signal_num, frame):
     261                        pass
     262
     263                signal.signal(signal.SIGINT, sig_int)
     264
     265        # create the executor for our jobs and handle the signal properly
     266        pool = multiprocessing.Pool(jobs, worker_init)
    266267
    267268        failed = False
     269
     270        def stop(x, y):
     271                print("Tests interrupted by user", file=sys.stderr)
     272                sys.exit(1)
     273        signal.signal(signal.SIGINT, stop)
    268274
    269275        # for each test to run
     
    354360                failed = 0
    355361
    356                 # check if the expected files aren't empty
    357                 if not options.regenerate_expected:
    358                         for t in tests:
    359                                 if is_empty(t.expect()):
    360                                         print('WARNING: test "{}" has empty .expect file'.format(t.target()), file=sys.stderr)
    361 
    362362                # for each build configurations, run the test
    363363                with Timed() as total_dur:
  • tests/typedefRedef.cfa

    r223a633 r33c3ded  
    2727typedef int ARR[];
    2828typedef int ARR[];
    29 #ifdef ERR1
    30 // if a typedef has an array dimension, it can only be redefined to the same dimension
     29// #ifdef ERR1
     30// if a typedef has an array dimension,
     31// it can only be redefined to the same dimension
    3132typedef int ARR[2];
    32 #endif
     33// #endif
    3334
    3435typedef int X;
     
    5354
    5455int main() {
    55         typedef int ARR[sz];
     56  typedef int ARR[sz];
    5657
    57         // can't redefine typedef which is VLA
     58  // can't redefine typedef which is VLA
    5859#if ERR1
    59         typedef int ARR[sz];
     60  typedef int ARR[sz];
    6061#endif
    6162
    62         Foo * x;
     63  Foo *x;
    6364
    64         typedef struct Bar Foo;
    65         Foo * y;
     65  typedef struct Bar Foo;
     66  Foo *y;
    6667
    67         typedef int *** pt;
    68 
    69         #pragma message( "Compiled" )                   // force non-empty .expect file
     68  typedef int *** pt;
    7069}
  • tests/typeof.cfa

    r223a633 r33c3ded  
    11int main() {
    2         int *v1;
    3         typeof(v1) v2;
    4         typeof(*v1) v3[4];
    5         char *v4[4];
    6         typeof(typeof(char *)[4]) v5;
    7         typeof (int *) v6;
    8         typeof( int ( int, int p ) ) *v7;
    9         typeof( [int] ( int, int p ) ) *v8;
    10         (typeof(v1)) v2; // cast with typeof
    11         printf( "done\n" );                             // non-empty .expect file
     2    int *v1;
     3    typeof(v1) v2;
     4    typeof(*v1) v3[4];
     5    char *v4[4];
     6    typeof(typeof(char *)[4]) v5;
     7    typeof (int *) v6;
     8    typeof( int ( int, int p ) ) *v7;
     9    typeof( [int] ( int, int p ) ) *v8;
     10    (typeof(v1)) v2; // cast with typeof
    1211}
  • tests/variableDeclarator.cfa

    r223a633 r33c3ded  
    1010// Created On       : Wed Aug 17 08:41:42 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 07:46:17 2020
    13 // Update Count     : 13
     12// Last Modified On : Tue Nov  6 18:02:16 2018
     13// Update Count     : 2
    1414//
    1515
     
    1818int (f2);
    1919
    20 int * f3;
    21 int ** f4;
    22 int * const * f5;
     20int *f3;
     21int **f4;
     22int * const *f5;
    2323int * const * const f6;
    2424
    25 int * (f7);
    26 int ** (f8);
    27 int * const * (f9);
     25int *(f7);
     26int **(f8);
     27int * const *(f9);
    2828int * const * const (f10);
    2929
    30 int (* f11);
    31 int (** f12);
    32 int (* const * f13);
     30int (*f11);
     31int (**f12);
     32int (* const *f13);
    3333int (* const * const f14);
    3434
    35 int f15[0];
     35int f15[];
    3636int f16[10];
    37 int (f17[0]);
     37int (f17[]);
    3838int (f18[10]);
    3939
    40 int * f19[0];
    41 int * f20[10];
    42 int ** f21[0];
    43 int ** f22[10];
    44 int * const * f23[0];
    45 int * const * f24[10];
    46 int * const * const f25[0];
     40int *f19[];
     41int *f20[10];
     42int **f21[];
     43int **f22[10];
     44int * const *f23[];
     45int * const *f24[10];
     46int * const * const f25[];
    4747int * const * const f26[10];
    4848
    49 int *(f27[0]);
     49int *(f27[]);
    5050int *(f28[10]);
    51 int **(f29[0]);
     51int **(f29[]);
    5252int **(f30[10]);
    53 int * const *(f31[0]);
     53int * const *(f31[]);
    5454int * const *(f32[10]);
    55 int * const * const (f33[0]);
     55int * const * const (f33[]);
    5656int * const * const (f34[10]);
    5757
    58 int (* f35)[];
    59 int (* f36)[10];
    60 int (** f37)[];
    61 int (** f38)[10];
    62 int (* const * f39)[];
    63 int (* const * f40)[10];
     58int (*f35)[];
     59int (*f36)[10];
     60int (**f37)[];
     61int (**f38)[10];
     62int (* const *f39)[];
     63int (* const *f40)[10];
    6464int (* const * const f41)[];
    6565int (* const * const f42)[10];
    6666
    67 int f43[0][3];
     67int f43[][3];
    6868int f44[3][3];
    69 int (f45[0])[3];
     69int (f45[])[3];
    7070int (f46[3])[3];
    71 int ((f47[0]))[3];
     71int ((f47[]))[3];
    7272int ((f48[3]))[3];
    7373
    74 int * f49[0][3];
    75 int * f50[3][3];
    76 int ** f51[0][3];
    77 int ** f52[3][3];
    78 int * const * f53[0][3];
    79 int * const * f54[3][3];
    80 int * const * const f55[0][3];
     74int *f49[][3];
     75int *f50[3][3];
     76int **f51[][3];
     77int **f52[3][3];
     78int * const *f53[][3];
     79int * const *f54[3][3];
     80int * const * const f55[][3];
    8181int * const * const f56[3][3];
    8282
    83 int (* f57[0][3]);
    84 int (* f58[3][3]);
    85 int (** f59[0][3]);
    86 int (** f60[3][3]);
    87 int (* const * f61[0][3]);
    88 int (* const * f62[3][3]);
    89 int (* const * const f63[0][3]);
     83int (*f57[][3]);
     84int (*f58[3][3]);
     85int (**f59[][3]);
     86int (**f60[3][3]);
     87int (* const *f61[][3]);
     88int (* const *f62[3][3]);
     89int (* const * const f63[][3]);
    9090int (* const * const f64[3][3]);
    9191
     
    9393int (f66)(int);
    9494
    95 int * f67(int);
    96 int ** f68(int);
    97 int * const * f69(int);
     95int *f67(int);
     96int **f68(int);
     97int * const *f69(int);
    9898int * const * const f70(int);
    9999
     
    104104int * const * const (f74)(int);
    105105
    106 int (* f75)(int);
    107 int (** f76)(int);
    108 int (* const * f77)(int);
     106int (*f75)(int);
     107int (**f76)(int);
     108int (* const *f77)(int);
    109109int (* const * const f78)(int);
    110110
    111 int (*(* f79)(int))();
     111int (*(*f79)(int))();
    112112int (*(* const f80)(int))();
    113113int (* const(* const f81)(int))();
     
    119119//int fe2()[];                          // returning an array
    120120//int fe3()();                          // returning a function
    121 //int (* fe4)()();                              // returning a function
    122 //int ((* fe5())())[];                  // returning an array
     121//int (*fe4)()();                               // returning a function
     122//int ((*fe5())())[];                   // returning an array
    123123
    124 #ifdef __CFA__
    125124// Cforall extensions
    126125
     
    130129const * const * int cf6;
    131130
    132 [0] int cf15;
     131[] int cf15;
    133132[10] int cf16;
    134133
    135 [0] * int cf19;
     134[] * int cf19;
    136135[10] * int cf20;
    137 int ** cf21[0];
     136int **cf21[];
    138137[10] * * int cf22;
    139 [0] * const * int cf23;
     138[] * const * int cf23;
    140139[10] * const * int cf24;
    141 [0] const * const * int cf25;
     140[] const * const * int cf25;
    142141[10] const * const * int cf26;
    143142
     
    151150const * const * [10] int cf42;
    152151
    153 [0][3] int cf43;
     152[][3] int cf43;
    154153[3][3] int cf44;
    155154
    156 [0][3] * int cf49;
     155[][3] * int cf49;
    157156[3][3] * int cf50;
    158 [0][3] * * int cf51;
     157[][3] * * int cf51;
    159158[3][3] * * int cf52;
    160 [0][3] const * int cf53;
     159[][3] const * int cf53;
    161160[3][3] * const * int cf54;
    162 [0][3] const * const * int cf55;
     161[][3] const * const * int cf55;
    163162[3][3] const * const * int cf56;
    164163
     
    174173
    175174*[]*[]* [ *[]*[] int ]( *[]*[] int, *[]*[] int ) v3;
    176 #endif // __CFA__
    177175
    178176//Dummy main
    179 int main( int argc, char const * argv[] ) {
    180         #pragma message( "Compiled" )                                           // force non-empty .expect file
     177int main(int argc, char const *argv[])
     178{
     179        return 0;
    181180}
    182181
  • tests/voidPtr.cfa

    r223a633 r33c3ded  
    1313        if ( ! a ) {
    1414                abort();
    15         }
    16         printf( "done\n" );                             // non-empty .expect file
     15        }       
    1716}
    1817
  • tests/warnings/.expect/self-assignment.txt

    r223a633 r33c3ded  
    2424... to:
    2525  reference to signed int
    26 warnings/self-assignment.cfa: In function '_X4mainFi___1':
    27 warnings/self-assignment.cfa:36:9: note: #pragma message: Compiled
  • tests/warnings/self-assignment.cfa

    r223a633 r33c3ded  
    1010// Created On       : Thu Mar 1 13:53:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep 27 09:24:34 2020
    13 // Update Count     : 6
     12// Last Modified On : Wed Feb 20 07:56:17 2019
     13// Update Count     : 3
    1414//
    1515
     
    3131        s.i = s.i;
    3232        t.s.i = t.s.i;
    33 
    34         #pragma message( "Compiled" )                   // force non-empty .expect file
    3533}
    3634
    3735// Local Variables: //
    3836// tab-width: 4 //
    39 // compile-command: "cfa self-assignment.cfa" //
     37// compile-command: "cfa dtor-early-exit" //
    4038// End: //
  • tests/zombies/structMember.cfa

    r223a633 r33c3ded  
    5353// C useless declarations
    5454
    55 #ifdef ERROR
    5655        int;
    5756        TD;
     
    7170        W(int);
    7271        W(int).X;
    73 #endif // ERROR
    7472};
    7573
  • tools/gdb/utils-gdb.py

    r223a633 r33c3ded  
    4444STACK = []
    4545
     46# A global variable to keep all system task name
     47SysTask_Name = ["uLocalDebuggerReader", "uLocalDebugger", "uProcessorTask", "uBootTask", "uSystemTask",
     48"uProcessorTask", "uPthread", "uProfiler"]
     49
    4650not_supported_error_msg = "Not a supported command for this language"
    4751
     
    97101        return cluster_root
    98102
    99 def get_sched_lock():
    100         """
    101         Return: gdb.Value of __scheduler_lock
    102         """
    103         lock = gdb.parse_and_eval('_X16__scheduler_lockPS20__scheduler_RWLock_t_1')
    104         if lock.address == 0x0:
    105                 print('No scheduler lock, program terminated')
    106         return lock
    107 
    108 def all_clusters():
    109         if not is_cforall():
    110                 return None
    111 
    112         cluster_root = get_cluster_root()
    113         if cluster_root.address == 0x0:
    114                 return
    115 
    116         curr = cluster_root
    117         ret = [curr]
    118 
    119         while True:
    120                 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1']
    121                 if curr == cluster_root:
    122                         break
    123 
    124                 ret.append(curr)
    125 
    126         return ret
    127 
    128 def all_processors():
    129         if not is_cforall():
    130                 return None
    131 
    132         cfa_t = get_cfa_types()
    133 
    134         # get processors from registration to the RWlock
    135         lock = get_sched_lock()
    136 
    137         #get number of elements
    138         count = lock['_X5readyVj_1']
    139 
    140         #find all the procs
    141         raw_procs = [lock['_X4dataPS21__scheduler_lock_id_t_1'][i]['_X6handleVPS16__processor_id_t_1'] for i in range(count)]
    142 
    143         # pre cast full procs
    144         procs = [p.cast(cfa_t.processor_ptr) for p in raw_procs if p['_X9full_procb_1']]
    145 
    146         # sort procs by clusters
    147         return sorted(procs, key=lambda p: p['_X4cltrPS7cluster_1'])
    148 
    149 def tls_for_pthread(pthrd):
    150         prev = gdb.selected_thread()
    151         inf = gdb.selected_inferior()
    152 
    153         thrd = inf.thread_from_thread_handle( pthrd )
    154         thrd.switch()
    155         tls = gdb.parse_and_eval('&_X9kernelTLSS16KernelThreadData_1')
    156 
    157         prev.switch()
    158         return tls
    159 
    160 def tls_for_proc(proc):
    161         return tls_for_pthread(proc['_X13kernel_threadm_1'])
    162 
    163 def thread_for_pthread(pthrd):
    164         return tls_for_pthread(pthrd)['_X11this_threadVPS7$thread_1']
    165 
    166 def thread_for_proc(proc):
    167         return tls_for_proc(proc)['_X11this_threadVPS7$thread_1']
    168 
    169 
    170 
    171103def find_curr_thread():
    172104        # btstr = gdb.execute('bt', to_string = True).splitlines()
     
    176108        # return btstr[0].split('this=',1)[1].split(',')[0].split(')')[0]
    177109        return None
     110
     111def all_clusters():
     112        if not is_cforall():
     113                return None
     114
     115        cluster_root = get_cluster_root()
     116        if cluster_root.address == 0x0:
     117                return
     118
     119        curr = cluster_root
     120        ret = [curr]
     121
     122        while True:
     123                curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1']
     124                if curr == cluster_root:
     125                        break
     126
     127                ret.append(curr)
     128
     129        return ret
     130
    178131
    179132def lookup_cluster(name = None):
     
    286239        """Cforall: Display currently known processors
    287240Usage:
    288         info processors                 : print out all the processors
     241        info processors                 : print out all the processors in the Main Cluster
     242        info processors all             : print out all processors in all clusters
    289243        info processors <cluster_name>  : print out all processors in a given cluster
    290244"""
     
    293247                super(Processors, self).__init__('info processors', gdb.COMMAND_USER)
    294248
    295         def print_processor(self, processor):
    296                 should_stop = processor['_X12do_terminateVb_1']
    297                 if not should_stop:
    298                         midle = processor['_X6$linksS7$dlinks_S9processor__1']['_X4nextS9$mgd_link_Y13__tE_generic___1']['_X4elemPY13__tE_generic__1'] != 0x0
    299                         end   = processor['_X6$linksS7$dlinks_S9processor__1']['_X4nextS9$mgd_link_Y13__tE_generic___1']['_X10terminatorPv_1'] != 0x0
    300 
    301                         status = 'Idle' if midle or end else 'Active'
    302                 else:
     249        def print_processor(self, name, status, pending, address):
     250                print('{:>20}  {:>11}  {:>13}  {:>20}'.format(name, status, pending, address))
     251
     252        def iterate_procs(self, root, active):
     253                if root == 0x0:
     254                        return
     255
     256                cfa_t = get_cfa_types()
     257                curr = root
     258
     259                while True:
     260                        processor = curr
     261                        should_stop = processor['_X12do_terminateVb_1']
    303262                        stop_count  = processor['_X10terminatedS9semaphore_1']['_X5counti_1']
    304                         status_str  = 'Last Thread' if stop_count >= 0 else 'Terminating'
    305                         status      = '{}({},{})'.format(status_str, should_stop, stop_count)
    306 
    307                 print('{:>20}  {:>11}  {:<7}  {:<}'.format(
    308                         processor['_X4namePKc_1'].string(),
    309                         status,
    310                         str(processor['_X18pending_preemptionb_1']),
    311                         str(processor)
    312                 ))
    313                 tls = tls_for_proc( processor )
    314                 thrd = tls['_X11this_threadVPS7$thread_1']
    315                 if thrd != 0x0:
    316                         tname = '{} {}'.format(thrd['self_cor']['name'].string(), str(thrd))
    317                 else:
    318                         tname = None
    319 
    320                 print('{:>20}  {}'.format('Thread', tname))
    321                 print('{:>20}  {}'.format('TLS', tls))
     263                        if not should_stop:
     264                                status = 'Active' if active else 'Idle'
     265                        else:
     266                                status_str  = 'Last Thread' if stop_count >= 0 else 'Terminating'
     267                                status      = '{}({},{})'.format(status_str, should_stop, stop_count)
     268
     269                        self.print_processor(processor['_X4namePKc_1'].string(),
     270                                        status, str(processor['_X18pending_preemptionb_1']), str(processor)
     271                                )
     272
     273                        curr = curr['_X4nodeS28__processor____dbg_node_proc_1']['_X4nextPS9processor_1']
     274
     275                        if curr == root or curr == 0x0:
     276                                break
    322277
    323278        #entry point from gdb
     
    327282
    328283                if not arg:
     284                        clusters = [lookup_cluster(None)]
     285                elif arg == "all":
    329286                        clusters = all_clusters()
    330287                else:
     
    335292                        return
    336293
    337                 procs = all_processors()
    338 
    339                 print('{:>20}  {:>11}  {:<7}  {}'.format('Processor', '', 'Pending', 'Object'))
    340                 print('{:>20}  {:>11}  {:<7}  {}'.format('Name', 'Status', 'Yield', 'Address'))
    341                 cl = None
    342                 for p in procs:
    343                         # if this is a different cluster print it
    344                         if cl != p['_X4cltrPS7cluster_1']:
    345                                 if cl:
    346                                         print()
    347                                 cl = p['_X4cltrPS7cluster_1']
    348                                 print('Cluster {}'.format(cl['_X4namePKc_1'].string()))
    349 
    350                         # print the processor information
    351                         self.print_processor(p)
     294                cfa_t = get_cfa_types()
     295                for cluster in clusters:
     296                        print('Cluster: "{}"({})'.format(cluster['_X4namePKc_1'].string(), cluster.cast(cfa_t.cluster_ptr)))
     297
     298                        active_root = cluster.cast(cfa_t.cluster_ptr) \
     299                                        ['_X5procsS8__dllist_S9processor__1'] \
     300                                        ['_X4headPY15__TYPE_generic__1'] \
     301                                        .cast(cfa_t.processor_ptr)
     302
     303                        idle_root = cluster.cast(cfa_t.cluster_ptr) \
     304                                        ['_X5idlesS8__dllist_S9processor__1'] \
     305                                        ['_X4headPY15__TYPE_generic__1'] \
     306                                        .cast(cfa_t.processor_ptr)
     307
     308                        if idle_root != 0x0 or active_root != 0x0:
     309                                self.print_processor('Name', 'Status', 'Pending Yield', 'Address')
     310                                self.iterate_procs(active_root, True)
     311                                self.iterate_procs(idle_root, False)
     312                        else:
     313                                print("No processors on cluster")
    352314
    353315                print()
Note: See TracChangeset for help on using the changeset viewer.