Changes in / [33c3ded:223a633]


Ignore:
Files:
146 added
123 deleted
157 edited

Legend:

Unmodified
Added
Removed
  • Jenkins/FullBuild

    r33c3ded r223a633  
    1717
    1818                                parallel (
    19                                         clang_x86: { trigger_build( 'gcc-8',   'x86' ) },
    20                                         gcc_5_x86: { trigger_build( 'gcc-7',   'x86' ) },
     19                                        gcc_8_x86: { trigger_build( 'gcc-8',   'x86' ) },
     20                                        gcc_7_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

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

    r33c3ded r223a633  
    113113creation_cfa_generator_DURATION = 1000000000
    114114creation_upp_coroutine_DURATION = ${creation_cfa_coroutine_eager_DURATION}
    115 creation_cfa_thread_DURATION = 10000000
    116 creation_upp_thread_DURATION = ${creation_cfa_thread_DURATION}
    117115creation_DURATION = 10000000
    118116
     
    148146
    149147cleancsv:
    150         rm -f compile.csv basic.csv ctxswitch.csv mutex.csv scheduling.csv
     148        rm -f compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv
    151149
    152150jenkins$(EXEEXT): cleancsv
     
    159157        +make mutex.csv
    160158        -+make mutex.diff.csv
    161         +make scheduling.csv
    162         -+make scheduling.diff.csv
     159        +make schedint.csv
     160        -+make schedint.diff.csv
    163161@DOifskipcompile@
    164162        cat compile.csv
     
    169167        cat mutex.csv
    170168        -cat mutex.diff.csv
    171         cat scheduling.csv
    172         -cat scheduling.diff.csv
     169        cat schedint.csv
     170        -cat schedint.diff.csv
    173171
    174172compile.csv:
     
    200198        $(srcdir)/fixcsv.sh $@
    201199
    202 scheduling.csv:
     200schedint.csv:
    203201        echo "building $@"
    204202        echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@
     
    291289ctxswitch-python_coroutine$(EXEEXT):
    292290        $(BENCH_V_PY)echo "#!/bin/sh" > a.out
    293         echo "python3.7 $(srcdir)/ctxswitch/python_cor.py" >> a.out
     291        echo "python3 $(srcdir)/ctxswitch/python_cor.py \"$$""@\"" >> a.out
    294292        chmod a+x a.out
    295293
    296294ctxswitch-nodejs_coroutine$(EXEEXT):
    297295        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    298         echo "nodejs $(srcdir)/ctxswitch/node_cor.js" >> a.out
     296        echo "nodejs $(srcdir)/ctxswitch/node_cor.js \"$$""@\"" >> a.out
    299297        chmod a+x a.out
    300298
    301299ctxswitch-nodejs_await$(EXEEXT):
    302300        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    303         echo "nodejs $(srcdir)/ctxswitch/node_await.js" >> a.out
     301        echo "nodejs $(srcdir)/ctxswitch/node_await.js \"$$""@\"" >> a.out
    304302        chmod a+x a.out
    305303
     
    313311        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/ctxswitch/JavaThread.java
    314312        echo "#!/bin/sh" > a.out
    315         echo "java JavaThread" >> a.out
     313        echo "java JavaThread \"$$""@\"" >> a.out
    316314        chmod a+x a.out
    317315
     
    355353        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/mutex/JavaThread.java
    356354        echo "#!/bin/sh" > a.out
    357         echo "java JavaThread" >> a.out
     355        echo "java JavaThread \"$$""@\"" >> a.out
    358356        chmod a+x a.out
    359357
     
    387385        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/schedint/JavaThread.java
    388386        echo "#!/bin/sh" > a.out
    389         echo "java JavaThread" >> a.out
     387        echo "java JavaThread \"$$""@\"" >> a.out
    390388        chmod a+x a.out
    391389
     
    454452creation-python_coroutine$(EXEEXT):
    455453        $(BENCH_V_PY)echo "#!/bin/sh" > a.out
    456         echo "python3.7 $(srcdir)/creation/python_cor.py" >> a.out
     454        echo "python3 $(srcdir)/creation/python_cor.py \"$$""@\"" >> a.out
    457455        chmod a+x a.out
    458456
    459457creation-nodejs_coroutine$(EXEEXT):
    460458        $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out
    461         echo "nodejs $(srcdir)/creation/node_cor.js" >> a.out
     459        echo "nodejs $(srcdir)/creation/node_cor.js \"$$""@\"" >> a.out
    462460        chmod a+x a.out
    463461
     
    471469        $(BENCH_V_JAVAC)javac -d $(builddir) $(srcdir)/creation/JavaThread.java
    472470        echo "#!/bin/sh" > a.out
    473         echo "java JavaThread" >> a.out
     471        echo "java JavaThread \"$$""@\"" >> a.out
    474472        chmod a+x a.out
    475473
     
    492490
    493491compile-array$(EXEEXT):
    494         $(CFACOMPILE) -fsyntax-only -w $(testdir)/array.cfa
     492        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/array.cfa
    495493
    496494compile-attributes$(EXEEXT):
    497         $(CFACOMPILE) -fsyntax-only -w $(testdir)/attributes.cfa
     495        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/attributes.cfa
    498496
    499497compile-empty$(EXEEXT):
    500         $(CFACOMPILE) -fsyntax-only -w $(srcdir)/compile/empty.cfa
     498        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(srcdir)/compile/empty.cfa
    501499
    502500compile-expression$(EXEEXT):
    503         $(CFACOMPILE) -fsyntax-only -w $(testdir)/expression.cfa
     501        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/expression.cfa
    504502
    505503compile-io$(EXEEXT):
    506         $(CFACOMPILE) -fsyntax-only -w $(testdir)/io1.cfa
     504        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/io1.cfa
    507505
    508506compile-monitor$(EXEEXT):
    509         $(CFACOMPILE) -fsyntax-only -w $(testdir)/concurrent/monitor.cfa
     507        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/monitor.cfa
    510508
    511509compile-operators$(EXEEXT):
    512         $(CFACOMPILE) -fsyntax-only -w $(testdir)/operators.cfa
     510        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/operators.cfa
    513511
    514512compile-thread$(EXEEXT):
    515         $(CFACOMPILE) -fsyntax-only -w $(testdir)/concurrent/thread.cfa
     513        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/concurrent/thread.cfa
    516514
    517515compile-typeof$(EXEEXT):
    518         $(CFACOMPILE) -fsyntax-only -w $(testdir)/typeof.cfa
     516        $(CFACOMPILE) -DNO_COMPILED_PRAGMA -fsyntax-only -w $(testdir)/typeof.cfa
    519517
    520518## =========================================================================================================
  • benchmark/creation/JavaThread.java

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

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

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

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

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

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

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

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

    r33c3ded r223a633  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Sep  4 13:56:52 2020
    14 %% Update Count     : 383
     13%% Last Modified On : Mon Oct  5 09:34:46 2020
     14%% Update Count     : 464
    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}}
    7257
    7358\usepackage{pslatex}                                    % reduce size of san serif font
     
    244229\usepackage{listings}                                                                   % format program code
    245230\usepackage{lstlang}
    246 
    247 \newcommand{\CFADefaults}{%
     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}{%
    248254\lstset{
    249 language=CFA,
    250255columns=fullflexible,
    251256basicstyle=\linespread{0.9}\sf,                 % reduce line spacing and use sanserif font
     
    262267belowskip=3pt,
    263268% replace/adjust listing characters that look bad in sanserif
    264 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     269literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    265270        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    266271        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
    267 moredelim=**[is][\color{red}]{?}{?},    % red highlighting ?...? (registered trademark symbol) emacs: C-q M-.
     272}% lstset
     273}% CFAStyle
     274
     275\ifdefined\CFALatin% extra Latin-1 escape characters
     276\lstnewenvironment{cfa}[1][]{
     277\lstset{
     278language=CFA,
     279moredelim=**[is][\color{red}]{®}{®},    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    268280moredelim=**[is][\color{blue}]{ß}{ß},   % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    269281moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    270282moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     283% replace/adjust listing characters that look bad in sanserif
     284add to literate={`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    271285}% lstset
    272 }% CFADefaults
    273 \newcommand{\CFAStyle}{%
    274 \CFADefaults
     286\lstset{#1}
     287}{}
    275288% inline code ©...© (copyright symbol) emacs: C-q M-)
    276289\lstMakeShortInline©                                    % single-character for \lstinline
    277 }% CFAStyle
    278 
    279 \lstnewenvironment{cfa}[1][]
    280 {\CFADefaults\lstset{#1}}
    281 {}
     290\else% regular ASCI characters
     291\lstnewenvironment{cfa}[1][]{
     292\lstset{
     293language=CFA,
     294escapechar=\$,                                                  % LaTeX escape in CFA code
     295moredelim=**[is][\color{red}]{@}{@},    % red highlighting @...@
     296}% lstset
     297\lstset{#1}
     298}{}
     299% inline code @...@ (at symbol)
     300\lstMakeShortInline@                                    % single-character for \lstinline
     301\fi%
    282302
    283303% Local Variables: %
  • doc/LaTeXmacros/lstlang.sty

    r33c3ded r223a633  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Tue Jan  8 14:40:33 2019
    11 %% Update Count     : 21
     10%% Last Modified On : Wed Sep 23 22:40:04 2020
     11%% Update Count     : 24
    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, _Generic, _Imaginary, __imag, __imag__,
     117                __float80, float80, __float128, float128, forall, ftype, generator, _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, thread,
     119                otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, 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++}{}
     127\lstdefinelanguage{C++}[ANSI]{C++}{
     128        morekeywords={nullptr,}
     129}
    128130
    129131% uC++ programming language, based on ANSI C++
  • doc/bibliography/pl.bib

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

    r33c3ded r223a633  
    224224{}
    225225\lstnewenvironment{C++}[1][]                            % use C++ style
    226 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     226{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    227227{}
    228228\lstnewenvironment{uC++}[1][]
    229 {\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     229{\lstset{language=uC++,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    230230{}
    231231\lstnewenvironment{Go}[1][]
    232 {\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     232{\lstset{language=Golang,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    233233{}
    234234\lstnewenvironment{python}[1][]
    235 {\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     235{\lstset{language=python,moredelim=**[is][\protect\color{red}]{`}{`}}\lstset{#1}}
    236236{}
    237237\lstnewenvironment{java}[1][]
    238 {\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     238{\lstset{language=java,moredelim=**[is][\protect\color{red}]{`}{`}}\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.
     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~\cite{Buhr90a}.
    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.
     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;
     2995each @N@ appears after the experiment name in the following tables.
    29952996The total time is divided by @N@ to obtain the average time for a benchmark.
    29962997Each benchmark experiment is run 13 times and the average appears in the table.
     2998For languages with a runtime JIT (Java, Node.js, Python), a single half-hour long experiment is run to check stability;
     2999all 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.
    29973000All 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
    30003001
    30013002\paragraph{Creation}
     
    30063007
    30073008\begin{multicols}{2}
    3008 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3009 \begin{cfa}
    3010 @coroutine@ MyCoroutine {};
     3009\begin{cfa}[xleftmargin=0pt]
     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}{@{}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           \\
    3039 Python generator                & 123.2         & 124.3         & 4.1           \\
    3040 Node.js generator               & 33.4          & 33.5          & 0.3           \\
    3041 Goroutine thread                & 751.0         & 750.5         & 3.1           \\
    3042 Rust tokio thread               & 1860.0        & 1881.1        & 37.6          \\
    3043 Rust thread                             & 53801.0       & 53896.8       & 274.9         \\
    3044 Java thread                             & 120274.0      & 120722.9      & 2356.7        \\
    3045 Pthreads thread                 & 31465.5       & 31419.5       & 140.4
     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           \\
     3039Python generator (10M)          & 123.2         & 124.3         & 4.1           \\
     3040Node.js generator (10M)         & 33.4          & 33.5          & 0.3           \\
     3041Goroutine thread (10M)          & 751.0         & 750.5         & 3.1           \\
     3042Rust tokio thread (10M)         & 1860.0        & 1881.1        & 37.6          \\
     3043Rust thread     (250K)                  & 53801.0       & 53896.8       & 274.9         \\
     3044Java thread (250K)                      & 119256.0      & 119679.2      & 2244.0        \\
     3045% Java thread (1 000 000)               & 123100.0      & 123052.5      & 751.6         \\
     3046Pthreads thread (250K)          & 31465.5       & 31419.5       & 140.4
    30463047\end{tabular}
    30473048\end{multicols}
     
    30523053Internal scheduling is measured using a cycle of two threads signalling and waiting.
    30533054Figure~\ref{f:schedint} shows the code for \CFA, with results in Table~\ref{t:schedint}.
    3054 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
    3055 Java 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.
     3055Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects.
     3056User-level threading has one kernel thread, eliminating contention between the threads (direct handoff of the kernel thread).
     3057Kernel-level threading has two kernel threads allowing some contention.
    30563058
    30573059\begin{multicols}{2}
    3058 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3059 \begin{cfa}
     3060\setlength{\tabcolsep}{3pt}
     3061\begin{cfa}[xleftmargin=0pt]
    30603062volatile int go = 0;
    3061 @condition c;@
    3062 @monitor@ M {} m1/*, m2, m3, m4*/;
    3063 void call( M & @mutex p1/*, p2, p3, p4*/@ ) {
    3064         @signal( c );@
    3065 }
    3066 void wait( M & @mutex p1/*, p2, p3, p4*/@ ) {
     3063`condition c;`
     3064`monitor` M {} m1/*, m2, m3, m4*/;
     3065void call( M & `mutex p1/*, p2, p3, p4*/` ) {
     3066        `signal( c );`
     3067}
     3068void wait( M & `mutex p1/*, p2, p3, p4*/` ) {
    30673069        go = 1; // continue other thread
    3068         for ( N ) { @wait( c );@ } );
     3070        for ( N ) { `wait( c );` } );
    30693071}
    30703072thread T {};
     
    30913093
    30923094\begin{tabular}{@{}r*{3}{D{.}{.}{5.2}}@{}}
    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           \\
    3098 Rust cond. variable                     & 7514.0        & 7437.4        & 397.2         \\
    3099 Java @notify@ monitor           & 9623.0        & 9654.6        & 236.2         \\
    3100 Pthreads cond. variable         & 5553.7        & 5576.1        & 345.6
     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           \\
     3100Rust cond. variable     (1M)            & 7514.0        & 7437.4        & 397.2         \\
     3101Java @notify@ monitor (1M)              & 8717.0        & 8774.1        & 471.8         \\
     3102% Java @notify@ monitor (100 000 000)           & 8634.0        & 8683.5        & 330.5         \\
     3103Pthreads cond. variable (1M)    & 5553.7        & 5576.1        & 345.6
    31013104\end{tabular}
    31023105\end{multicols}
     
    31073110External scheduling is measured using a cycle of two threads calling and accepting the call using the @waitfor@ statement.
    31083111Figure~\ref{f:schedext} shows the code for \CFA with results in Table~\ref{t:schedext}.
    3109 Note, the incremental cost of bulk acquire for \CFA, which is largely a fixed cost for small numbers of mutex objects.
     3112Note, the \CFA incremental cost for bulk acquire is a fixed cost for small numbers of mutex objects.
    31103113
    31113114\begin{multicols}{2}
    3112 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
     3115\setlength{\tabcolsep}{5pt}
    31133116\vspace*{-16pt}
    3114 \begin{cfa}
    3115 @monitor@ M {} m1/*, m2, m3, m4*/;
    3116 void call( M & @mutex p1/*, p2, p3, p4*/@ ) {}
    3117 void wait( M & @mutex p1/*, p2, p3, p4*/@ ) {
    3118         for ( N ) { @waitfor( call : p1/*, p2, p3, p4*/ );@ }
     3117\begin{cfa}[xleftmargin=0pt]
     3118`monitor` M {} m1/*, m2, m3, m4*/;
     3119void call( M & `mutex p1/*, p2, p3, p4*/` ) {}
     3120void wait( M & `mutex p1/*, p2, p3, p4*/` ) {
     3121        for ( N ) { `waitfor( call : p1/*, p2, p3, p4*/ );` }
    31193122}
    31203123thread T {};
     
    31333136\columnbreak
    31343137
    3135 \vspace*{-16pt}
     3138\vspace*{-18pt}
    31363139\captionof{table}{External-scheduling comparison (nanoseconds)}
    31373140\label{t:schedext}
    31383141\begin{tabular}{@{}r*{3}{D{.}{.}{3.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   \\
    3144 Go \lstinline[language=Golang]|select| channel  & 365.0 & 365.5 & 1.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   \\
     3147Go \lstinline[language=Golang]|select| channel (10M)    & 365.0 & 365.5 & 1.2
    31453148\end{tabular}
    31463149\end{multicols}
     
    31553158
    31563159\begin{multicols}{2}
    3157 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3158 \begin{cfa}
    3159 @monitor@ M {} m1/*, m2, m3, m4*/;
    3160 call( M & @mutex p1/*, p2, p3, p4*/@ ) {}
     3160\setlength{\tabcolsep}{3pt}
     3161\begin{cfa}[xleftmargin=0pt]
     3162`monitor` M {} m1/*, m2, m3, m4*/;
     3163call( M & `mutex p1/*, p2, p3, p4*/` ) {}
    31613164int main() {
    31623165        BENCH( for( N ) call( m1/*, m2, m3, m4*/ ); )
     
    31733176\label{t:mutex}
    31743177\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3175 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3176 test-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   \\
    3181 Goroutine mutex lock                    & 34.0  & 34.0  & 0.0   \\
    3182 Rust mutex lock                                 & 33.0  & 33.2  & 0.8   \\
    3183 Java synchronized method                & 31.0  & 31.0  & 0.0   \\
    3184 Pthreads mutex Lock                             & 31.0  & 31.1  & 0.4
     3178\multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3179test-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   \\
     3184Goroutine mutex lock (50M)                      & 34.0  & 34.0  & 0.0   \\
     3185Rust mutex lock (50M)                           & 33.0  & 33.2  & 0.8   \\
     3186Java synchronized method (50M)          & 31.0  & 30.9  & 0.5   \\
     3187% Java synchronized method (10 000 000 000)             & 31.0 & 30.2 & 0.9 \\
     3188Pthreads mutex Lock (50M)                       & 31.0  & 31.1  & 0.4
    31853189\end{tabular}
    31863190\end{multicols}
     
    32013205% To: "Peter A. Buhr" <pabuhr@plg2.cs.uwaterloo.ca>
    32023206% Date: Fri, 24 Jan 2020 13:49:18 -0500
    3203 % 
     3207%
    32043208% I can also verify that the previous version, which just tied a bunch of promises together, *does not* go back to the
    32053209% event loop at all in the current version of Node. Presumably they're taking advantage of the fact that the ordering of
     
    32113215
    32123216\begin{multicols}{2}
    3213 \lstset{language=CFA,moredelim=**[is][\color{red}]{@}{@},deletedelim=**[is][]{`}{`}}
    3214 \begin{cfa}[aboveskip=0pt,belowskip=0pt]
    3215 @coroutine@ C {};
    3216 void main( C & ) { for () { @suspend;@ } }
     3217\begin{cfa}[xleftmargin=0pt]
     3218`coroutine` C {};
     3219void main( C & ) { for () { `suspend;` } }
    32173220int main() { // coroutine test
    32183221        C c;
    3219         BENCH( for ( N ) { @resume( c );@ } )
     3222        BENCH( for ( N ) { `resume( c );` } )
    32203223        sout | result;
    32213224}
    32223225int main() { // thread test
    3223         BENCH( for ( N ) { @yield();@ } )
     3226        BENCH( for ( N ) { `yield();` } )
    32243227        sout | result;
    32253228}
     
    32343237\label{t:ctx-switch}
    32353238\begin{tabular}{@{}r*{3}{D{.}{.}{3.2}}@{}}
    3236 \multicolumn{1}{@{}c}{} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
    3237 C 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   \\
    3243 Python generator        & 40.9          & 41.3          & 1.5   \\
    3244 Node.js await           & 1852.2        & 1854.7        & 16.4  \\
    3245 Node.js generator       & 33.3          & 33.4          & 0.3   \\
    3246 Goroutine thread        & 143.0         & 143.3         & 1.1   \\
    3247 Rust async await        & 32.0          & 32.0          & 0.0   \\
    3248 Rust tokio thread       & 143.0         & 143.0         & 1.7   \\
    3249 Rust thread                     & 332.0         & 331.4         & 2.4   \\
    3250 Java thread                     & 405.0         & 415.0         & 17.6  \\
    3251 Pthreads thread         & 334.3         & 335.2         & 3.9
     3239\multicolumn{1}{@{}r}{N\hspace*{10pt}} & \multicolumn{1}{c}{Median} &\multicolumn{1}{c}{Average} & \multicolumn{1}{c@{}}{Std Dev} \\
     3240C 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   \\
     3246Python generator (100M)         & 40.9          & 41.3          & 1.5   \\
     3247Node.js await (5M)                      & 1852.2        & 1854.7        & 16.4  \\
     3248Node.js generator (100M)        & 33.3          & 33.4          & 0.3   \\
     3249Goroutine thread (100M)         & 143.0         & 143.3         & 1.1   \\
     3250Rust async await (100M)         & 32.0          & 32.0          & 0.0   \\
     3251Rust tokio thread (100M)        & 143.0         & 143.0         & 1.7   \\
     3252Rust thread (25M)                       & 332.0         & 331.4         & 2.4   \\
     3253Java 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 \\
     3256Pthreads thread (25M)           & 334.3         & 335.2         & 3.9
    32523257\end{tabular}
    32533258\end{multicols}
     
    32583263Languages using 1:1 threading based on pthreads can at best meet or exceed, due to language overhead, the pthread results.
    32593264Note, pthreads has a fast zero-contention mutex lock checked in user space.
    3260 Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions.
     3265Languages with M:N threading have better performance than 1:1 because there is no operating-system interactions (context-switching or locking).
     3266As well, for locking experiments, M:N threading has less contention if only one kernel thread is used.
    32613267Languages with stackful coroutines have higher cost than stackless coroutines because of stack allocation and context switching;
    32623268however, stackful \uC and \CFA coroutines have approximately the same performance as stackless Python and Node.js generators.
    32633269The \CFA stackless generator is approximately 25 times faster for suspend/resume and 200 times faster for creation than stackless Python and Node.js generators.
     3270The Node.js context-switch is costly when asynchronous await must enter the event engine because a promise is not fulfilled.
     3271Finally, the benchmark results correlate across programming languages with and without JIT, indicating the JIT has completed any runtime optimizations.
    32643272
    32653273
     
    33193327
    33203328The 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.
    3321 This 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.
     3329This 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.
    33223330
    33233331{%
  • doc/papers/concurrency/annex/local.bib

    r33c3ded r223a633  
    5959@manual{Cpp-Transactions,
    6060        keywords        = {C++, Transactional Memory},
    61         title           = {Technical Specification for C++ Extensions for Transactional Memory},
     61        title           = {Tech. Spec. 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

    r33c3ded r223a633  
    959959Software: Practice and Experience Editorial Office
    960960
     961
     962
     963Date: Wed, 2 Sep 2020 20:55:34 +0000
     964From: Richard Jones <onbehalfof@manuscriptcentral.com>
     965Reply-To: R.E.Jones@kent.ac.uk
     966To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
     967Subject: Software: Practice and Experience - Decision on Manuscript ID
     968 SPE-19-0219.R2
     969
     97002-Sep-2020
     971
     972Dear Dr Buhr,
     973
     974Many 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
     976Both 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
     9781) 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
     979Virtual 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
     9812) Kalibera, Tomas and Jones, Richard. Rigorous Benchmarking in Reasonable Time. ISMM  2013. https://doi.org/10.1145/2555670.2464160
     982Experimental 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
     984You 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
     986You 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
     988When 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
     990If 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 
     992Once again, thank you for submitting your manuscript to Software: Practice and Experience. I look forward to receiving your revision.
     993
     994Sincerely,
     995Richard
     996
     997Prof. Richard Jones
     998Editor, Software: Practice and Experience
     999R.E.Jones@kent.ac.uk
     1000
     1001Referee(s)' Comments to Author:
     1002
     1003Reviewing: 1
     1004
     1005Comments to the Author
     1006Overall, I felt that this draft was an improvement on previous drafts and I don't have further changes to request.
     1007
     1008I 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
     1011Reviewing: 2
     1012
     1013Comments to the Author
     1014First: 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
     1016At 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
     1018Finally, 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 
     1020minor points
     1021* don't start sentences with "However"
     1022* most downloaded isn't an "Award"
     1023
     1024
     1025
     1026Date: Thu, 1 Oct 2020 05:34:29 +0000
     1027From: Richard Jones <onbehalfof@manuscriptcentral.com>
     1028Reply-To: R.E.Jones@kent.ac.uk
     1029To: pabuhr@uwaterloo.ca
     1030Subject: Revision reminder - SPE-19-0219.R2
     1031
     103201-Oct-2020
     1033
     1034Dear Dr Buhr
     1035
     1036SPE-19-0219.R2
     1037
     1038This 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
     1040If 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
     1042I look forward to receiving your revision.
     1043
     1044Sincerely,
     1045
     1046Prof. Richard Jones
     1047Editor, Software: Practice and Experience
     1048
     1049https://mc.manuscriptcentral.com/spe
     1050
     1051
     1052
     1053Date: Tue, 6 Oct 2020 15:29:41 +0000
     1054From: Mayank Roy Chowdhury <onbehalfof@manuscriptcentral.com>
     1055Reply-To: speoffice@wiley.com
     1056To: tdelisle@uwaterloo.ca, pabuhr@uwaterloo.ca
     1057Subject: SPE-19-0219.R3 successfully submitted
     1058
     105906-Oct-2020
     1060
     1061Dear Dr Buhr,
     1062
     1063Your 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
     1065Your manuscript number is SPE-19-0219.R3.  Please mention this number in all future correspondence regarding this submission.
     1066
     1067You 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
     1070Thank you for submitting your manuscript to Software: Practice and Experience.
     1071
     1072Sincerely,
     1073
     1074Software: Practice and Experience Editorial Office
     1075
  • doc/refrat/refrat.tex

    r33c3ded r223a633  
    1111%% Created On       : Wed Apr  6 14:52:25 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Wed Jan 31 17:30:23 2018
    14 %% Update Count     : 108
     13%% Last Modified On : Mon Oct  5 09:02:53 2020
     14%% Update Count     : 110
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
    32 \usepackage{xspace}
    3332\usepackage{varioref}                                                                   % extended references
    34 \usepackage{listings}                                                                   % format program code
    3533\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3634\usepackage{latexsym}                                   % \Box glyph
    3735\usepackage{mathptmx}                                   % better math font with "times"
    3836\usepackage[usenames]{color}
    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 
     37\newcommand{\CFALatin}{}
    6438% inline code ©...© (copyright symbol) emacs: C-q M-)
    6539% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    6943% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    7044% 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}
    7162
    7263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    7364
     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
    7472% Names used in the document.
    75 \newcommand{\Version}{\input{../../version}}
     73\newcommand{\Version}{\input{build/version}}
    7674\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    7775\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
  • doc/theses/andrew_beach_MMath/thesis.tex

    r33c3ded r223a633  
    3434\usepackage[toc,abbreviations]{glossaries-extra}
    3535
    36 % Main glossary entries -- definitions of relevant terminology
    37 \newglossaryentry{computer}
    38 {
    39 name=computer,
    40 description={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 {
    49 type=nomenclature,
    50 name=dingledorf,
    51 description={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 {
    63 name={$\mathbf{v}$},
    64 sort={label},
    65 type=symbols,
    66 description={Random vector: a location in n-dimensional Cartesian space, where
    67                each dimensional component is determined by a random process}
    68 }
     36% Define all the glossaries.
     37\input{glossaries}
    6938
    7039% Generate the glossaries defined above.
  • doc/theses/fangren_yu_COOP_S20/Makefile

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

    r33c3ded r223a633  
    1 \documentclass[twoside,12pt]{article}
     1\documentclass[twoside,11pt]{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
    1314\usepackage{latexsym}                                   % \Box glyph
    1415\usepackage{mathptmx}                                   % better math font with "times"
     16\usepackage[toc]{appendix}                                                              % article does not have appendix
    1517\usepackage[usenames]{color}
    1618\input{common}                                          % common CFA document macros
    1719\usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref}
    1820\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
    1926
    2027\usepackage[pagewise]{lineno}
     
    2633\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    2734\newcommand{\NOTE}{\textbf{NOTE}}
     35\newcommand{\TODO}[1]{{\color{Purple}#1}}
    2836
    2937\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     
    3240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    3341
    34 \CFADefaults
     42\CFAStyle                                                                                               % CFA code-style for all languages
    3543\lstset{
    36 language=C++,                                                                                   % make C++ the default language
    37 escapechar=\$,                                                                                  % LaTeX escape in CFA code
    38 moredelim=**[is][\color{red}]{`}{`},
     44language=C++,moredelim=**[is][\color{red}]{@}{@}                % make C++ the default language
    3945}% lstset
    40 \lstMakeShortInline@%
    4146\lstnewenvironment{C++}[1][]                            % use C++ style
    42 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}}
    43 {}
     47{\lstset{language=C++,moredelim=**[is][\color{red}]{@}{@}}\lstset{#1}}{}
    4448
    4549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    8488\section{Overview}
    8589
    86 cfa-cc is the reference compiler for the \CFA programming language, which is a non-
    87 object-oriented extension to C.
    88 \CFA attempts to introduce productive modern programming language features to C
    89 while maintaining as much backward-compatibility as possible, so that most existing C
    90 programs can seamlessly work with \CFA.
    91 
    92 Since the \CFA project was dated back to the early 2000s, and only restarted in the past
    93 few years, there is a significant amount of legacy code in the current compiler codebase,
    94 with little proper documentation available. This becomes a difficulty while developing new
    95 features based on the previous implementations, and especially while diagnosing
    96 problems.
    97 
    98 Currently, the \CFA team is also facing another problem: bad compiler performance. For
    99 the development of a new programming language, writing a standard library is an
    100 important part. The incompetence of the compiler causes building the library files to take
    101 tens of minutes, making iterative development and testing almost impossible. There is
    102 ongoing effort to rewrite the core data structure of the compiler to overcome the
    103 performance issue, but many bugs may appear during the work, and lack of documentation
    104 makes debugging extremely difficult.
    105 
    106 This developer's reference will be continuously improved and eventually cover the
    107 compiler codebase. For now, the focus is mainly on the parts being rewritten, and also the
    108 performance bottleneck, namely the resolution algorithm. It is aimed to provide new
    109 developers to the project enough guidance and clarify the purposes and behavior of certain
    110 functions which are not mentioned in the previous \CFA research papers.
     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
     93Since 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.
     94The lack of documentation makes it difficult to develop new features from the current implementation and diagnose problems.
     95
     96Currently, the \CFA team is also facing poor compiler performance.
     97For the development of a new programming language, writing standard libraries is an important component.
     98The slow compiler causes building of the library files to take tens of minutes, making iterative development and testing almost impossible.
     99There 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
     101This developer's reference manual begins the documentation and should be continuously im\-proved until it eventually covers the entire compiler codebase.
     102For now, the focus is mainly on the parts being rewritten, and also the primary performance bottleneck, namely the resolution algorithm.
     103Its 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}.
    111104
    112105
    113106\section{Compiler Framework}
    114107
     108\CFA source code is first transformed into an abstract syntax tree (AST) by the parser before analyzed by the compiler.
     109
     110
    115111\subsection{AST Representation}
    116112
    117 Source code input is first transformed into abstract syntax tree (AST) representation by the
    118 parser before analyzed by the compiler.
    119 
    120 There are 4 major categories of AST nodes used by the compiler, along with some derived
    121 structures.
    122 
    123 \subsubsection{Declaration nodes}
     113
     114There are 4 major categories of AST nodes used by the compiler, along with some derived structures.
     115
     116\subsubsection{Declaration Nodes}
    124117
    125118A declaration node represents either of:
    126119\begin{itemize}
    127120\item
    128 Type declaration: struct, union, typedef or type parameter (see Appendix A.3)
    129 \item
    130 Variable declaration
    131 \item
    132 Function declaration
     121type declaration: @struct@, @union@, @typedef@ or type parameter (see \VRef[Appendix]{s:KindsTypeParameters})
     122\item
     123variable declaration
     124\item
     125function declaration
    133126\end{itemize}
    134127Declarations are introduced by standard C declarations, with the usual scoping rules.
    135 In addition, declarations can also be introduced by the forall clause (which is the origin
    136 of \CFA's name):
     128In addition, declarations can also be qualified by the \lstinline[language=CFA]@forall@ clause (which is the origin of \CFA's name):
    137129\begin{cfa}
    138 forall (<$\emph{TypeParameterList}$> | <$\emph{AssertionList}$>)
     130forall ( <$\emph{TypeParameterList}$> | <$\emph{AssertionList}$> )
    139131        $\emph{declaration}$
    140132\end{cfa}
    141 Type parameters in \CFA are similar to \CC template type parameters. The \CFA
    142 declaration
     133Type parameters in \CFA are similar to \CC template type parameters.
     134The \CFA declaration
    143135\begin{cfa}
    144136forall (dtype T) ...
    145137\end{cfa}
    146 behaves similarly as the \CC template declaration
     138behaves similarly to the \CC template declaration
    147139\begin{C++}
    148140template <typename T> ...
    149141\end{C++}
    150142
    151 Assertions are a distinctive feature of \CFA: contrary to the \CC template where
    152 arbitrary functions and operators can be used in a template definition, in a \CFA
    153 parametric function, operations on parameterized types must be declared in assertions.
    154 
     143Assertions are a distinctive feature of \CFA, similar to \emph{interfaces} in D and Go, and \emph{traits} in Rust.
     144Contrary 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.
    155145Consider the following \CC template:
    156146\begin{C++}
    157 template <typename T> int foo(T t) {
    158         return bar(t) + baz(t);
     147@template@ forall<typename T> T foo( T t ) {
     148        return t + t * t;
    159149}
    160150\end{C++}
    161 Unless bar and baz are also parametric functions taking any argument type, they must be
    162 declared in the assertions, or otherwise the code will not compile:
     151where there are no explicit requirements on the type @T@.
     152Therefore, the \CC compiler must deduce what operators are required during textual (macro) expansion of the template at each usage.
     153As a result, templates cannot be compiled.
     154\CFA assertions specify restrictions on type parameters:
    163155\begin{cfa}
    164 forall (dtype T | { int bar(T); int baz(t); }) int foo (T t) {
    165         return bar(t) + baz(t);
     156forall( dtype T | @{ T ?+?( T, T ); T ?*?( T, T ) }@ ) int foo ( T t ) {
     157        return t + t * t;
    166158}
    167159\end{cfa}
    168 Assertions are written using the usual function declaration syntax. The scope of type
    169 parameters and assertions is the following declaration.
    170 
    171 \subsubsection{Type nodes}
    172 
    173 A type node represents the type of an object or expression.
    174 Named types reference the corresponding type declarations. The type of a function is its
    175 function pointer type (same as standard C).
    176 With the addition of type parameters, named types may contain a list of parameter values
    177 (actual parameter types).
    178 
    179 \subsubsection{Statement nodes}
    180 
    181 Statement nodes represent the statements in the program, including basic expression
    182 statements, control flows and blocks.
     160Assertions are written using the usual \CFA function declaration syntax.
     161Only types with operators ``@+@'' and ``@*@'' work with this function, and the function prototype is sufficient to allow separate compilation.
     162
     163Type parameters and assertions are used in the following compiler data-structures.
     164
     165
     166\subsubsection{Type Nodes}
     167
     168Type nodes represent the type of an object or expression.
     169Named types reference the corresponding type declarations.
     170The type of a function is its function pointer type (same as standard C).
     171With the addition of type parameters, named types may contain a list of parameter values (actual parameter types).
     172
     173
     174\subsubsection{Statement Nodes}
     175
     176Statement nodes represent the executable statements in the program, including basic expression statements, control flows and blocks.
    183177Local declarations (within a block statement) are represented as declaration statements.
    184178
    185 \subsubsection{Expression nodes}
    186 
    187 Some expressions are represented differently in the compiler before and after resolution
    188 stage:
     179
     180\subsubsection{Expression Nodes}
     181
     182Some expressions are represented differently before and after the resolution stage:
    189183\begin{itemize}
    190184\item
    191 Name expressions: NameExpr pre-resolution, VariableExpr post-resolution
    192 \item
    193 Member expressions: UntypedMemberExpr pre-resolution, MemberExpr post-resolution
    194 \item
    195 Function call expressions (including overloadable operators): UntypedExpr pre-resolution, ApplicationExpr post-resolution
     185Name expressions: @NameExpr@ pre-resolution, @VariableExpr@ post-resolution
     186\item
     187Member expressions: @UntypedMemberExpr@ pre-resolution, @MemberExpr@ post-resolution
     188\item
     189\begin{sloppypar}
     190Function call expressions (including overloadable operators): @UntypedExpr@ pre-resolution, @ApplicationExpr@ post-resolution
     191\end{sloppypar}
    196192\end{itemize}
    197 The pre-resolution representations contain only the symbols. Post-resolution results link
    198 them to the actual variable and function declarations.
     193The pre-resolution representation contains only the symbols.
     194Post-resolution links them to the actual variable and function declarations.
    199195
    200196
    201197\subsection{Compilation Passes}
    202198
    203 Compilation steps are implemented as passes, which follows a general structural recursion
    204 pattern on the syntax tree.
    205 
    206 The basic work flow of compilation passes follows preorder and postorder traversal on
    207 tree data structure, implemented with visitor pattern, and can be loosely described with
    208 the following pseudocode:
    209 \begin{C++}
    210 Pass::visit (node_t node) {
    211         previsit(node);
    212         if (visit_children)
     199Compilation steps are implemented as passes, which follows a general structural recursion pattern on the syntax tree.
     200
     201The 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++}
     203Pass::visit( node_t node ) {
     204        previsit( node );
     205        if ( visit_children )
    213206                for each child of node:
    214                         child.accept(this);
    215         postvisit(node);
     207                        child.accept( this );
     208        postvisit( node );
    216209}
    217210\end{C++}
    218 Operations in previsit() happen in preorder (top to bottom) and operations in
    219 postvisit() happen in postorder (bottom to top). The precise order of recursive
    220 operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and
    221 @AST/Pass.impl.hpp@ (new).
    222 Implementations of compilation passes need to follow certain conventions:
     211Operations in @previsit@ happen in preorder (top to bottom) and operations in @postvisit@ happen in postorder (bottom to top).
     212The precise order of recursive operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and @AST/Pass.impl.hpp@ (new).
     213
     214Implementations of compilation passes follow certain conventions:
    223215\begin{itemize}
    224216\item
    225 Passes \textbf{should not} directly override the visit method (Non-virtual Interface
    226 principle); if a pass desires different recursion behavior, it should set
    227 @visit_children@ to false and perform recursive calls manually within previsit or
    228 postvisit procedures. To enable this option, inherit from @WithShortCircuiting@ mixin.
    229 \item
    230 previsit may mutate the node but \textbf{must not} change the node type or return null.
    231 \item
    232 postvisit may mutate the node, reconstruct it to a different node type, or delete it by
    233 returning null.
     217Passes \textbf{should not} directly override the visit method (Non-virtual Interface principle);
     218if a pass desires different recursion behaviour, it should set @visit_children@ to false and perform recursive calls manually within previsit or postvisit procedures.
     219To enable this option, inherit from the @WithShortCircuiting@ mixin.
     220\item
     221previsit may mutate the node but \textbf{must not} change the node type or return @nullptr@.
     222\item
     223postvisit may mutate the node, reconstruct it to a different node type, or delete it by returning @nullptr@.
    234224\item
    235225If the previsit or postvisit method is not defined for a node type, the step is skipped.
    236 If the return type is declared as void, the original node is returned by default. These
    237 behaviors are controlled by template specialization rules; see
    238 @Common/PassVisitor.proto.h@ (old) and @AST/Pass.proto.hpp@ (new) for details.
     226If the return type is declared as @void@, the original node is returned by default.
     227These behaviours are controlled by template specialization rules;
     228see @Common/PassVisitor.proto.h@ (old) and @AST/@ @Pass.proto.hpp@ (new) for details.
    239229\end{itemize}
    240230Other useful mixin classes for compilation passes include:
    241231\begin{itemize}
    242232\item
    243 WithGuards allows saving values of variables and restore automatically upon exiting
    244 the current node.
    245 \item
    246 WithVisitorRef creates a wrapped entity of current pass (the actual argument
    247 passed to recursive calls internally) for explicit recursion, usually used together
    248 with WithShortCircuiting.
    249 \item
    250 WithSymbolTable gives a managed symbol table with built-in scoping rule handling
    251 (\eg on entering and exiting a block statement)
     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)
    252238\end{itemize}
    253 \NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading
    254 resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures
    255 to its own scope, or otherwise they will not be picked up by template resolution:
     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:
    256240\begin{C++}
    257241class Pass2: public Pass1 {
    258         using Pass1::previsit;
    259         using Pass1::postvisit;
     242        @using Pass1::previsit;@
     243        @using Pass1::postvisit;@
    260244        // new procedures
    261245}
     
    263247
    264248
    265 \subsection{Data Structure Change WIP (new-ast)}
    266 
    267 It has been observed that excessive copying of syntax tree structures accounts for a
    268 majority of computation cost and significantly slows down the compiler. In the previous
    269 implementation of the syntax tree, every internal node has a unique parent; therefore all
    270 copies are required to duplicate everything down to the bottom. A new, experimental
    271 re-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
    273 of common sub-structures and only makes copies when necessary.
    274 
    275 The 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
    277 used to detect sharing and allows optimization. For a purely functional (a.k.a. immutable)
    278 data structure, all mutations are modelled by shallow copies along the path of mutation.
     249\subsection{Data Structure Change (new-ast)}
     250
     251It has been observed that excessive copying of syntax tree structures accounts for a majority of computation cost and significantly slows down the compiler.
     252In the previous implementation of the syntax tree, every internal node has a unique parent;
     253therefore all copies are required to duplicate the entire subtree.
     254A 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
     256The 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.
     257Reference counting is used to detect sharing and allowing certain optimizations.
     258For a purely functional (immutable) data-structure, all mutations are modelled by shallow copies along the path of mutation.
    279259With reference counting optimization, unique nodes are allowed to be mutated in place.
    280 This however, may potentially introduce some complications and bugs; a few issues are
    281 discussed near the end of this section.
    282 
    283 \subsubsection{Source: AST/Node.hpp}
    284 
    285 class @ast::Node@ is the base class of all new-ast node classes, which implements
    286 reference counting mechanism. Two different counters are recorded: ``strong'' reference
    287 count for number of nodes semantically owning it; ``weak'' reference count for number of
    288 nodes holding a mere reference and only need to observe changes.
    289 class @ast::ptr_base@ is the smart pointer implementation and also takes care of
    290 resource management.
    291 
    292 Direct access through the smart pointer is read-only. A mutable access should be obtained
    293 by calling shallowCopy or mutate as below.
    294 
    295 Currently, the weak pointers are only used to reference declaration nodes from a named
    296 type, or a variable expression. Since declaration nodes are intended to denote unique
    297 entities in the program, weak pointers always point to unique (unshared) nodes. This may
    298 change in the future, and weak references to shared nodes may introduce some problems;
     260This however, may potentially introduce some complications and bugs;
     261a few issues are discussed near the end of this section.
     262
     263
     264\subsubsection{Source: \lstinline{AST/Node.hpp}}
     265
     266Class @ast::Node@ is the base class of all new-ast node classes, which implements reference counting mechanism.
     267Two 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.
     269Class @ast::ptr_base@ is the smart pointer implementation and also takes care of resource management.
     270
     271Direct access through the smart pointer is read-only.
     272A mutable access should be obtained by calling @shallowCopy@ or mutate as below.
     273
     274Currently, the weak pointers are only used to reference declaration nodes from a named type, or a variable expression.
     275Since declaration nodes are intended to denote unique entities in the program, weak pointers always point to unique (unshared) nodes.
     276This property may change in the future, and weak references to shared nodes may introduce some problems;
    299277see mutate function below.
    300278
    301 All node classes should always use smart pointers in the structure and should not use raw
    302 pointers.
    303 
     279All node classes should always use smart pointers in structure definitions versus raw pointers.
     280Function
    304281\begin{C++}
    305282void ast::Node::increment(ref_type ref)
    306283\end{C++}
    307 Increments this node's strong or weak reference count.
     284increments this node's strong or weak reference count.
     285Function
    308286\begin{C++}
    309287void ast::Node::decrement(ref_type ref, bool do_delete = true)
    310288\end{C++}
    311 Decrements this node's strong or weak reference count. If strong reference count reaches
    312 zero, the node is deleted by default.
    313 \NOTE: Setting @do_delete@ to false may result in a detached node. Subsequent code should
    314 manually delete the node or assign it to a strong pointer to prevent memory leak.
     289decrements this node's strong or weak reference count.
     290If strong reference count reaches zero, the node is deleted.
     291\NOTE: Setting @do_delete@ to false may result in a detached node.
     292Subsequent code should manually delete the node or assign it to a strong pointer to prevent memory leak.
     293
    315294Reference counting functions are internally called by @ast::ptr_base@.
     295Function
    316296\begin{C++}
    317297template<typename node_t>
    318298node_t * shallowCopy(const node_t * node)
    319299\end{C++}
    320 Returns a mutable, shallow copy of node: all child pointers are pointing to the same child
    321 nodes.
     300returns a mutable, shallow copy of node: all child pointers are pointing to the same child nodes.
     301Function
    322302\begin{C++}
    323303template<typename node_t>
    324304node_t * mutate(const node_t * node)
    325305\end{C++}
    326 If node is unique (strong reference count is 1), returns a mutable pointer to the same node.
    327 Otherwise, returns shallowCopy(node).
    328 It is an error to mutate a shared node that is weak-referenced. Currently this does not
    329 happen. The problem may appear once weak pointers to shared nodes (\eg expression
    330 nodes) 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
    333 issue is presented at the end of this section.
     306returns a mutable pointer to the same node, if the node is unique (strong reference count is 1);
     307otherwise, it returns @shallowCopy(node)@.
     308It is an error to mutate a shared node that is weak-referenced.
     309Currently this does not happen.
     310A problem may appear once weak pointers to shared nodes (\eg expression nodes) are used;
     311special care is needed.
     312
     313\NOTE: This naive uniqueness check may not be sufficient in some cases.
     314A discussion of the issue is presented at the end of this section.
     315Functions
    334316\begin{C++}
    335317template<typename node_t, typename parent_t, typename field_t, typename assn_t>
    336 const node_t * mutate_field(const node_t * node, field_t parent_t::*field, assn_t && val)
     318const node_t * mutate_field(const node_t * node, field_t parent_t::* field, assn_t && val)
    337319\end{C++}
    338320\begin{C++}
     
    342324                field_t && val)
    343325\end{C++}
    344 Helpers for mutating a field on a node using pointer to member (creates shallow copy
    345 when necessary).
    346 
    347 \subsubsection{Issue: Undetected sharing}
    348 
    349 The @mutate@ behavior described above has a problem: deeper shared nodes may be
     326are 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
     331The @mutate@ behaviour described above has a problem: deeper shared nodes may be
    350332mistakenly considered as unique. \VRef[Figure]{f:DeepNodeSharing} shows how the problem could arise:
    351333\begin{figure}
     
    355337\label{f:DeepNodeSharing}
    356338\end{figure}
    357 Suppose that we are working on the tree rooted at P1, which
    358 is logically the chain P1-A-B and P2 is irrelevant, and then
    359 mutate(B) is called. The algorithm considers B as unique since
    360 it is only directly owned by A. However, the other tree P2-A-B
    361 indirectly shares the node B and is therefore wrongly mutated.
    362 
    363 To partly address this problem, if the mutation is called higher up the tree, a chain
    364 mutation helper can be used:
    365 
    366 \subsubsection{Source: AST/Chain.hpp}
    367 
     339Given the tree rooted at P1, which is logically the chain P1-A-B, and P2 is irrelevant, assume @mutate(B)@ is called.
     340The algorithm considers B as unique since it is only directly owned by A.
     341However, the other tree P2-A-B indirectly shares the node B and is therefore wrongly mutated.
     342
     343To 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
     347Function
    368348\begin{C++}
    369349template<typename node_t, Node::ref_type ref_t>
    370350auto chain_mutate(ptr_base<node_t, ref_t> & base)
    371351\end{C++}
    372 This function returns a chain mutator handle which takes pointer-to-member to go down
    373 the tree while creating shallow copies as necessary; see @struct _chain_mutator@ in the
    374 source code for details.
    375 
    376 For example, in the above diagram, if mutation of B is wanted while at P1, the call using
    377 @chain_mutate@ looks like the following:
     352returns a chain mutator handle that takes pointer-to-member to go down the tree, while creating shallow copies as necessary;
     353see @struct _chain_mutator@ in the source code for details.
     354
     355For example, in the above diagram, if mutation of B is wanted while at P1, the call using @chain_mutate@ looks like the following:
    378356\begin{C++}
    379357chain_mutate(P1.a)(&A.b) = new_value_of_b;
    380358\end{C++}
    381 Note that if some node in chain mutate is shared (therefore shallow copied), it implies that
    382 every node further down will also be copied, thus correctly executing the functional
    383 mutation algorithm. This example code creates copies of both A and B and performs
    384 mutation on the new nodes, so that the other tree P2-A-B is untouched.
    385 However, 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
    387 experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up,
    388 this issue does not actually happen. It should be addressed in the future when other
    389 compilation passes are migrated to new-ast and many of them contain procedural
    390 mutations, 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 ???
     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.
     360This 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.
     361However, if a pass traverses down to node B and performs mutation, for example, in @postvisit(B)@, information on sharing higher up is lost.
     362Since 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.
     363It 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
    395366\section{Compiler Algorithm Documentation}
    396367
    397 This documentation currently covers most of the resolver, data structures used in variable
    398 and expression resolution, and a few directly related passes. Later passes involving code
    399 generation is not included yet; documentation for those will be done afterwards.
     368This compiler algorithm documentation covers most of the resolver, data structures used in variable and expression resolution, and a few directly related passes.
     369Later passes involving code generation are not included yet;
     370documentation for those will be done latter.
     371
    400372
    401373\subsection{Symbol Table}
    402374
    403 \NOTE: For historical reasons, the symbol table data structure was called ``indexer'' in the
    404 old implementation. Hereby we will be using the name SymbolTable everywhere.
    405 The symbol table stores a mapping from names to declarations and implements a similar
    406 name 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
    407 name space rule is that typedef aliases are no longer considered ordinary identifiers.
    408 In addition to C tag types (struct, union, enum), \CFA introduces another tag type, trait,
    409 which is a named collection of assertions.
    410 
    411 \subsubsection{Source: AST/SymbolTable.hpp}
    412 
    413 \subsubsection{Source: SymTab/Indexer.h}
    414 
     375\NOTE: For historical reasons, the symbol-table data-structure is called @indexer@ in the old implementation.
     376Hereby, the name is changed to @SymbolTable@.
     377The 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.}
     378The difference in name-space rule is that @typedef@ aliases are no longer considered ordinary identifiers.
     379In 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
     384Function
    415385\begin{C++}
    416386SymbolTable::addId(const DeclWithType * decl)
    417387\end{C++}
    418 Since \CFA allows overloading of variables and functions, ordinary identifier names need
    419 to 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
    420 making adaptations to \CFA specific features, mainly assertions and overloaded variables
    421 by type. Naming conflicts are handled by mangled names; lookup by name returns a list of
    422 declarations with the same literal identifier name.
    423 
     388provides name mangling of identifiers, since \CFA allows overloading of variables and functions.
     389The 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
     391Naming conflicts are handled by mangled names;
     392lookup by name returns a list of declarations with the same identifier name.
     393Functions
    424394\begin{C++}
    425395SymbolTable::addStruct(const StructDecl * decl)
     
    428398SymbolTable::addTrait(const TraitDecl * decl)
    429399\end{C++}
    430 Adds a tag type declaration to the symbol table.
     400add a tag-type declaration to the symbol table.
     401Function
    431402\begin{C++}
    432403SymbolTable::addType(const NamedTypeDecl * decl)
    433404\end{C++}
    434 Adds a typedef alias to the symbol table.
    435 
    436 \textbf{C Incompatibility Note}: Since Cforall allows using struct, union and enum type names
    437 without the keywords, typedef names and tag type names cannot be disambiguated by
    438 syntax rules. Currently the compiler puts them together and disallows collision. The
    439 following program is valid C but not valid Cforall:
     405adds 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.
     408Currently the compiler puts them together and disallows collision.
     409The following program is valid C but invalid \CFA (and \CC):
    440410\begin{C++}
    441411struct A {};
     412typedef int A; // gcc: ok, cfa: Cannot redefine typedef A
     413struct A sa; // C disambiguates via struct prefix
     414A ia;
     415\end{C++}
     416In practices, such usage is extremely rare, and hence, this change (as in \CC) has minimal impact on existing C programs.
     417The declaration
     418\begin{C++}
     419struct A {};
     420typedef struct A A; // A is an alias for struct A
     421A a;
     422struct A b;
     423\end{C++}
     424is not an error because the alias name is identical to the original.
     425Finally, the following program is allowed in \CFA:
     426\begin{C++}
    442427typedef int A;
    443 // gcc: ok, cfa: Cannot redefine typedef A
    444 \end{C++}
    445 In actual practices however, such usage is extremely rare, and typedef struct A A; is
    446 not considered an error, but silently discarded. Therefore, we expect this change to have
    447 minimal impact on existing C programs.
    448 Meanwhile, the following program is allowed in Cforall:
    449 \begin{C++}
    450 typedef int A;
    451 void A();
     428void A(); // name mangled
    452429// gcc: A redeclared as different kind of symbol, cfa: ok
    453430\end{C++}
     431because the function name is mangled.
     432
    454433
    455434\subsection{Type Environment and Unification}
    456435
    457 The core of parametric type resolution algorithm.
    458 Type Environment organizes type parameters in \textbf{equivalent classes} and maps them to
    459 actual types. Unification is the algorithm that takes two (possibly parametric) types and
    460 parameter mappings and attempts to produce a common type by matching the type
    461 environments.
     436The following core ideas underlie the parametric type-resolution algorithm.
     437A type environment organizes type parameters into \textbf{equivalent classes} and maps them to actual types.
     438Unification 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.
    462439
    463440The unification algorithm is recursive in nature and runs in two different modes internally:
    464441\begin{itemize}
    465442\item
    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
    469 common type.
     443Exact unification mode requires equivalent parameters to match perfectly.
     444\item
     445Inexact unification mode allows equivalent parameters to be converted to a common type.
    470446\end{itemize}
    471 For 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 
    474 Within inexact mode, types are allowed to differ on their cv-qualifiers; additionally, if a
    475 type never appear either in parameter list or as the base type of a pointer, it may also be
    476 widened (i.e. safely converted). As Cforall currently does not implement subclassing similar
    477 to object-oriented languages, widening conversions are on primitive types only, for
    478 example the conversion from int to long.
    479 
    480 The need for two unification modes come from the fact that parametric types are
    481 considered compatible only if all parameters are exactly the same (not just compatible).
    482 Pointer types also behaves similarly; in fact, they may be viewed as a primitive kind of
    483 parametric types. @int*@ and @long*@ are different types, just like @vector(int)@ and
    484 @vector(long)@ are, for the parametric type @vector(T)@.
    485 
    486 The resolver should use the following ``@public@'' functions:\footnote{
    487 Actual code also tracks assertions on type parameters; those extra arguments are omitted here for
    488 conciseness.}
    489 
    490 
    491 \subsubsection{Source: ResolvExpr/Unify.cc}
    492 
    493 \begin{C++}
    494 bool unify(const Type *type1, const Type *type2, TypeEnvironment &env,
    495 OpenVarSet &openVars, const SymbolTable &symtab, Type *&commonType)
    496 \end{C++}
    497 Attempts to unify @type1@ and @type2@ with current type environment.
    498 
    499 If operation succeeds, @env@ is modified by combining the equivalence classes of matching
    500 parameters in @type1@ and @type2@, and their common type is written to commonType.
    501 
    502 If operation fails, returns false.
    503 \begin{C++}
    504 bool typesCompatible(const Type * type1, const Type * type2, const
    505 SymbolTable &symtab, const TypeEnvironment &env)
    506 bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type *
    507 type2, const SymbolTable &symtab, const TypeEnvironment &env)
    508 \end{C++}
    509 
    510 Determines if type1 and type2 can possibly be the same type. The second version ignores
    511 the outermost cv-qualifiers if present.\footnote{
    512 In const \lstinline@int * const@, only the second \lstinline@const@ is ignored.}
    513 
    514 The call has no side effect.
    515 
    516 \NOTE: No attempts are made to widen the types (exact unification is used), although the
    517 function names may suggest otherwise. E.g. @typesCompatible(int, long)@ returns false.
     447For 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
     449Within the inexact mode, types are allowed to differ on their cv-qualifiers (\eg @const@, @volatile@, \etc);
     450additionally, 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).
     451As \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
     453The 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).
     454Pointer types also behaves similarly;
     455in 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
     458The resolver uses the following @public@ functions:\footnote{
     459Actual 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
     464Function
     465\begin{C++}
     466bool unify(const Type * type1, const Type * type2, TypeEnvironment & env,
     467        OpenVarSet & openVars, const SymbolTable & symtab, Type *& commonType)
     468\end{C++}
     469returns a boolean indicating if the unification succeeds or fails after attempting to unify @type1@ and @type2@ within current type environment.
     470If 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@.
     471If the unify fails, nothing changes.
     472Functions
     473\begin{C++}
     474bool typesCompatible(const Type * type1, const Type * type2, const SymbolTable & symtab,
     475        const TypeEnvironment & env)
     476bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type * type2,
     477        const SymbolTable & symtab, const TypeEnvironment & env)
     478\end{C++}
     479return a boolean indicating if types @type1@ and @type2@ can possibly be the same type.
     480The second version ignores the outermost cv-qualifiers if present.\footnote{
     481In \lstinline@const int * const@, only the second \lstinline@const@ is ignored.}
     482These 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.
    518485
    519486
    520487\subsection{Expression Resolution}
    521488
    522 The design of the current version of expression resolver is outlined in the Ph.D. Thesis from
    523 Aaron Moss~\cite{Moss19}.
    524 
     489The design of the current version of expression resolver is outlined in the Ph.D.\ thesis by Aaron Moss~\cite{Moss19}.
    525490A summary of the resolver algorithm for each expression type is presented below.
    526491
    527 All overloadable operators are modelled as function calls. For a function call,
    528 interpretations of the function and arguments are found recursively. Then the following
    529 steps produce a filtered list of valid interpretations:
     492All overloadable operators are modelled as function calls.
     493For a function call, interpretations of the function and arguments are found recursively.
     494Then the following steps produce a filtered list of valid interpretations:
    530495\begin{enumerate}
    531496\item
    532 From all possible combinations of interpretations of the function and arguments,
    533 those where argument types may be converted to function parameter types are
    534 considered valid.
     497From all possible combinations of interpretations of the function and arguments, those where argument types may be converted to function parameter types are considered valid.
    535498\item
    536499Valid interpretations with the minimum sum of argument costs are kept.
    537500\item
    538 Argument costs are then discarded; the actual cost for the function call expression is
    539 the sum of conversion costs from the argument types to parameter types.
    540 \item
    541 For each return type, the interpretations with satisfiable assertions are then sorted
    542 by actual cost computed in step 3. If for a given type, the minimum cost
    543 interpretations are not unique, it is said that for that return type the interpretation
    544 is ambiguous. If the minimum cost interpretation is unique but contains an
    545 ambiguous argument, it is also considered ambiguous.
     501\label{p:argcost}
     502Argument 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}
     505For each return type, the interpretations with satisfiable assertions are then sorted by actual cost computed in step~\ref{p:argcost}.
     506If for a given type, the minimum cost interpretations are not unique, that return type is ambiguous.
     507If the minimum cost interpretation is unique but contains an ambiguous argument, it is also ambiguous.
    546508\end{enumerate}
    547 Therefore, for each return type, the resolver produces either of:
     509Therefore, for each return type, the resolver produces:
    548510\begin{itemize}
    549511\item
    550 No alternatives
    551 \item
    552 A single valid alternative
    553 \item
    554 An ambiguous alternative
     512no alternatives
     513\item
     514a single valid alternative
     515\item
     516an ambiguous alternative
    555517\end{itemize}
    556 Note that an ambiguous alternative may be discarded at the parent expressions because a
    557 different return type matches better for the parent expressions.
    558 
    559 The non-overloadable expressions in Cforall are: cast expressions, address-of (unary @&@)
    560 expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional
    561 expression (@?:@).
    562 
    563 For a cast expression, the convertible argument types are kept. Then the result is selected
    564 by lowest argument cost, and further by lowest conversion cost to target type. If the lowest
    565 cost is still not unique, or an ambiguous argument interpretation is selected, the cast
    566 expression is ambiguous. In an expression statement, the top level expression is implicitly
    567 cast to void.
     518\NOTE: an ambiguous alternative may be discarded at the parent expressions because a different return type matches better for the parent expressions.
     519
     520The \emph{non}-overloadable expressions in \CFA are: cast expressions, address-of (unary @&@) expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional expression (@?:@).
     521
     522For a cast expression, the convertible argument types are kept.
     523Then the result is selected by lowest argument cost, and further by lowest conversion cost to target type.
     524If the lowest cost is still not unique or an ambiguous argument interpretation is selected, the cast expression is ambiguous.
     525In an expression statement, the top level expression is implicitly cast to @void@.
    568526
    569527For an address-of expression, only lvalue results are kept and the minimum cost is selected.
    570528
    571 For logical expressions @&&@ and @||@, arguments are implicitly cast to bool, and follow the rule
    572 of cast expression as above.
    573 
    574 For the ternary conditional expression, the condition is implicitly cast to bool, and the
    575 branch expressions must have compatible types. Each pair of compatible branch
    576 expression types produce a possible interpretation, and the cost is defined as the sum of
    577 expression costs plus the sum of conversion costs to the common type.
    578 
    579 TODO: Write a specification for expression costs.
     529For logical expressions @&&@ and @||@, arguments are implicitly cast to @bool@, and follow the rules fr cast expression above.
     530
     531For the ternary conditional expression, the condition is implicitly cast to @bool@, and the branch expressions must have compatible types.
     532Each 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
     537There were some unclear parts in the previous documentation in the cost system, as described in the Moss thesis~\cite{Moss19}, section 4.1.2.
     538Some clarification are presented in this section.
     539
     540\begin{enumerate}
     541\item
     542Conversion to a type denoted by parameter may incur additional cost if the match is not exact.
     543For 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
     546The 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.
     547A higher specialization level is favoured if argument conversion costs are equal.
     548
     549\item
     550Coercion of pointer types is only allowed in explicit cast expressions;
     551the only allowed implicit pointer casts are adding qualifiers to the base type and cast to @void*@, and these counts as safe conversions.
     552Note that implicit cast from @void *@ to other pointer types is no longer valid, as opposed to standard C.
     553\end{enumerate}
    580554
    581555
    582556\subsection{Assertion Satisfaction}
    583557
    584 The resolver tries to satisfy assertions on expressions only when it is needed: either while
    585 selecting from multiple alternatives of a same result type for a function call (step 4 of
    586 resolving function calls), or upon reaching the top level of an expression statement.
    587 
    588 Unsatisfiable alternatives are discarded. Satisfiable alternatives receive \textbf{implicit
    589 parameters}: in Cforall, parametric functions are designed such that they can be compiled
    590 separately, as opposed to \CC templates which are only compiled at instantiation. Given a
    591 parametric function definition:
     558The 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
     560Unsatisfiable alternatives are discarded.
     561Satisfiable alternatives receive \textbf{implicit parameters}: in \CFA, parametric functions may be separately compiled, as opposed to \CC templates which are only compiled at instantiation.
     562Given the parametric function-definition:
    592563\begin{C++}
    593564forall (otype T | {void foo(T);})
    594565void bar (T t) { foo(t); }
    595566\end{C++}
    596 The function bar does not know which @foo@ to call when compiled without knowing the call
    597 site, so it requests a function pointer to be passed as an extra argument. At the call site,
    598 implicit parameters are automatically inserted by the compiler.
    599 
    600 \textbf{TODO}: Explain how recursive assertion satisfaction and polymorphic recursion work.
    601 
     567the 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.
     568At the call site, implicit parameters are automatically inserted by the compiler.
     569
     570Implementation of implicit parameters is discussed in \VRef[Appendix]{s:ImplementationParametricFunctions}.
    602571
    603572\section{Tests}
     
    605574\subsection{Test Suites}
    606575
    607 Automatic test suites are located under the @tests/@ directory. A test case consists of an
    608 input CFA source file (name ending with @.cfa@), and an expected output file located
    609 in @.expect/@ directory relative to the source file, with the same file name ending with @.txt@.
    610 So a test named @tuple/tupleCast@ has the following files, for example:
     576Automatic test suites are located under the @tests/@ directory.
     577A 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@.
     578For example, the test named @tests/tuple/tupleCast.cfa@ has the following files, for example:
    611579\begin{C++}
    612580tests/
    613 ..     tuple/
    614 ......     .expect/
    615 ..........       tupleCast.txt
    616 ......     tupleCast.cfa
    617 \end{C++}
    618 If compilation fails, the error output is compared to the expect file. If compilation succeeds,
    619 the built program is run and its output compared to the expect file.
    620 To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of
    621 test names to be run, or @--all@ to run all tests. The test script reports test cases
    622 fail/success, compilation time and program run time.
     581        tuple/
     582                .expect/
     583                        tupleCast.txt
     584                tupleCast.cfa
     585\end{C++}
     586If compilation fails, the error output is compared to the expect file.
     587If the compilation succeeds but does not generate an executable, the compilation output is compared to the expect file.
     588If the compilation succeeds and generates an executable, the executable is run and its output is compared to the expect file.
     589To 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.
     590The test script reports test cases fail/success, compilation time and program run time.
     591To see all the options available for @test.py@ using the @--help@ option.
    623592
    624593
    625594\subsection{Performance Reports}
    626595
    627 To turn on performance reports, pass @-S@ flag to the compiler.
    628 
    629 3 kinds of performance reports are available:
     596To turn on performance reports, pass the @-XCFA -S@ flag to the compiler.
     597Three kinds of performance reports are available:
    630598\begin{enumerate}
    631599\item
     
    639607@Common/Stats/Counter.h@.
    640608\end{enumerate}
    641 It is suggested to run performance tests with optimized build (@g++@ flag @-O3@)
    642 
     609It 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
     618A 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
     623A 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
     627A 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
     642Restricted to the type for the last parameter in a function, it provides a type-safe way to implement variadic functions.
     643Note 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
     651In 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++}
     653void 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++}
     661GCC 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;
     668size of a parametric type must also be known if referenced directly (\ie not as a pointer).
     669
     670The 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
     673All types, variables, and functions are candidates of implicit parameters
     674\item
     675The parameter (assertion) name must match the actual declarations.
     676\end{enumerate}
     677
     678For example, the \CFA function declaration
     679\begin{cfa}
     680forall( otype T | { int foo( T, int ); } )
     681int bar(T);
     682\end{cfa}
     683after 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++}
     685int bar( T, size_t, void (*)(T&), void (*)(T&), int (*)(T, int) );
     686\end{C++}
     687The implicit parameter approach has an apparent issue: when the satisfying declaration is also parametric, it may require its own implicit parameters too.
     688That also causes the supplied implicit parameter to have a different \textbf{actual} type than the \textbf{nominal} type, so it cannot be passed directly.
     689Therefore, a wrapper with matching actual type must be created, and it is here where GCC nested functions are used internally by the compiler.
     690
     691Consider the following program:
     692\begin{cfa}
     693int assertion(int);
     694
     695forall( otype T | { int assertion(T); } )
     696void foo(T);
     697
     698forall(otype T | { void foo(T); } )
     699void bar(T t) {
     700        foo(t);
     701}
     702\end{cfa}
     703The \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
     706void foo(T, int (*)(T));
     707
     708void bar(T t, void (*foo)(T)) {
     709        foo(t);
     710}
     711\end{C++}
     712However, when @bar(1)@ is called, @foo@ cannot be directly provided as an argument:
     713\begin{C++}
     714bar(1, foo); // WRONG: foo has different actual type
     715\end{C++}
     716and 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++}
     725Nested assertions and implicit parameter creation may continue indefinitely.
     726This issue is a limitation of implicit parameter implementation.
     727In 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.
     728The \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).
    643729
    644730\bibliographystyle{plain}
  • doc/user/Makefile

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

    r33c3ded r223a633  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Mar  6 13:34:52 2020
    14 %% Update Count     : 3924
     13%% Last Modified On : Mon Oct  5 08:57:29 2020
     14%% Update Count     : 3998
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
    32 \usepackage{xspace}
    3332\usepackage{varioref}                                                                   % extended references
    34 \usepackage{listings}                                                                   % format program code
     33\usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig}
     34\renewcommand{\thesubfigure}{\alph{subfigure})}
    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 \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 
     39\newcommand{\CFALatin}{}
    6340% inline code ©...© (copyright symbol) emacs: C-q M-)
    6441% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    6845% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    6946% 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}
    7075
    7176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    7984\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    8085\newcommand{\KWC}{K-W C\xspace}
    81 
    82 \newsavebox{\LstBox}
    8386
    8487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    253256
    254257The 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):
    255 \begin{lstlisting}
     258\begin{cfa}
    256259®forall( otype T )® T identity( T val ) { return val; }
    257260int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
    258 \end{lstlisting}
     261\end{cfa}
    259262% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
    260263\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}.
     
    275278\begin{comment}
    276279A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array:
    277 \begin{lstlisting}
     280\begin{cfa}
    278281void * bsearch( const void * key, const void * base, size_t dim, size_t size,
    279282                                int (* compar)( const void *, const void * ));
     
    284287double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    285288double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
    286 \end{lstlisting}
     289\end{cfa}
    287290which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
    288 \begin{lstlisting}
     291\begin{cfa}
    289292forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
    290293        int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ }
     
    297300double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
    298301int posn = bsearch( 5.0, vals, 10 );
    299 \end{lstlisting}
     302\end{cfa}
    300303The nested function ©comp© provides the hidden interface from typed \CFA to untyped (©void *©) C, plus the cast of the result.
    301304Providing a hidden ©comp© function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
     
    305308\CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations.
    306309For example, it is possible to write a type-safe \CFA wrapper ©malloc© based on the C ©malloc©:
    307 \begin{lstlisting}
     310\begin{cfa}
    308311forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    309312int * ip = malloc(); §\C{// select type and size from left-hand side}§
    310313double * dp = malloc();
    311314struct S {...} * sp = malloc();
    312 \end{lstlisting}
     315\end{cfa}
    313316where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    314317\end{comment}
     
    943946the same level as a ©case© clause; the target label may be case ©default©, but only associated
    944947with the current ©switch©/©choose© statement.
    945 
    946 
    947 \subsection{Loop Control}
    948 
    949 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
    950 \begin{itemize}
    951 \item
    952 The 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
    954 An empty conditional implies comparison value of ©1© (true).
    955 \item
    956 A comparison N is implicit up-to exclusive range [0,N©®)®©.
    957 \item
    958 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
    959 \item
    960 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
    961 \item
    962 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
    963 \item
    964 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
    965 \item
    966 The 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
    972 The up-to range uses operator ©+=© for increment;
    973 \item
    974 The 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}
    980948
    981949\begin{figure}
     
    10861054
    10871055
     1056\subsection{Loop Control}
     1057
     1058The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
     1059\begin{itemize}
     1060\item
     1061The 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
     1063An empty conditional implies comparison value of ©1© (true).
     1064\item
     1065A comparison N is implicit up-to exclusive range [0,N©®)®©.
     1066\item
     1067A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
     1068\item
     1069The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
     1070\item
     1071The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
     1072\item
     1073The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
     1074\item
     1075The 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
     1081The up-to range uses operator ©+=© for increment;
     1082\item
     1083The 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
    10881091%\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}}
    10891092\subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}}
     
    10951098for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
    10961099\VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels.
    1097 The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
     1100The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
    10981101
    10991102\begin{figure}
    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
     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
    11231130} // compound
    11241131\end{cfa}
    1125 &
    1126 \begin{cfa}
     1132\end{lrbox}
     1133
     1134\begin{lrbox}{\myboxB}
     1135\begin{cfa}[tabsize=3]
    11271136{
    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}
     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}
    11741169\caption{Multi-level Exit}
    11751170\label{f:MultiLevelExit}
     
    14261421try {
    14271422        f(...);
    1428 } catch( E e ; §boolean-predicate§ ) {          §\C[8cm]{// termination handler}§
     1423} catch( E e ; §boolean-predicate§ ) {          §\C{// termination handler}§
    14291424        // recover and continue
    1430 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§
     1425} catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§
    14311426        // repair and return
    14321427} finally {
     
    34913486For 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.
    34923487\begin{cquote}
    3493 \begin{lrbox}{\LstBox}
     3488\begin{lrbox}{\myboxA}
    34943489\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    34953490int x;   double y   char z;
     
    34973492\end{lrbox}
    34983493\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}}
    3499 \multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\
     3494\multicolumn{1}{@{}l@{}}{\usebox\myboxA} \\
    35003495\multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}}       & \multicolumn{1}{c}{\textbf{Python}}   \\
    35013496\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     
    66726667For 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.
    66736668Without 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}
    66746672
    66756673\CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in
     
    67216719
    67226720        // §\CFA§ safe general allocation, fill, resize, alignment, array
    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 );
     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}§
    67436743
    67446744        // §\CFA§ safe initialization/copy, i.e., implicit size specification
  • libcfa/prelude/builtins.c

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

    r33c3ded r223a633  
    8888inst_thread_headers_nosrc = \
    8989        bits/random.hfa \
     90        concurrency/clib/cfathread.h \
    9091        concurrency/invoke.h \
    9192        concurrency/kernel/fwd.hfa
     
    103104        concurrency/alarm.cfa \
    104105        concurrency/alarm.hfa \
     106        concurrency/clib/cfathread.cfa \
    105107        concurrency/CtxSwitch-@ARCHITECTURE@.S \
    106108        concurrency/invoke.c \
  • libcfa/src/bits/containers.hfa

    r33c3ded r223a633  
    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;
    159170                }
    160171
  • libcfa/src/bits/locks.hfa

    r33c3ded r223a633  
    164164
    165165        struct $thread;
    166         extern void park( __cfaabi_dbg_ctx_param );
    167         extern void unpark( struct $thread * this __cfaabi_dbg_ctx_param2 );
     166        extern void park( void );
     167        extern void unpark( struct $thread * this );
    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( __cfaabi_dbg_ctx );
     193                                                park();
    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 __cfaabi_dbg_ctx2 );
     212                                                unpark( expected );
    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( __cfaabi_dbg_ctx );
     246                                        park();
    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 __cfaabi_dbg_ctx2 );
     258                        unpark( got );
    259259                        return true;
    260260                }
  • libcfa/src/concurrency/CtxSwitch-i386.S

    r33c3ded r223a633  
    1010// Created On       : Tue Dec 6 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Aug 16 08:46:22 2020
    13 // Update Count     : 4
     12// Last Modified On : Sun Sep  6 18:23:37 2020
     13// Update Count     : 5
    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
    53         // Having pushed three words (= 12 bytes) on the stack, the
    54         // argument is now at 8 + 12 = 20(%esp)
     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).
    5555
    5656        movl 20(%esp),%eax
  • libcfa/src/concurrency/alarm.cfa

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

    r33c3ded r223a633  
    4747
    4848//-----------------------------------------------------------------------------
    49 FORALL_DATA_INSTANCE(CoroutineCancelled,
    50                 (dtype coroutine_t | sized(coroutine_t)), (coroutine_t))
     49FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
    5150
    5251struct __cfaehm_node {
     
    5958void mark_exception(CoroutineCancelled(T) *) {}
    6059
    61 forall(dtype T | sized(T))
     60forall(dtype T)
    6261void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
    6362        dst->the_coroutine = src->the_coroutine;
     
    7776        exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
    7877
     78        // TODO: Remove explitate vtable set once trac#186 is fixed.
    7979        CoroutineCancelled(T) except;
     80        except.virtual_table = &get_exception_vtable(&except);
    8081        except.the_coroutine = &cor;
    8182        except.the_exception = except;
     
    9192
    9293// minimum feasible stack size in bytes
    93 #define MinStackSize 1000
     94static const size_t MinStackSize = 1000;
    9495extern size_t __page_size;                              // architecture pagesize HACK, should go in proper runtime singleton
    9596
  • libcfa/src/concurrency/coroutine.hfa

    r33c3ded r223a633  
    2222//-----------------------------------------------------------------------------
    2323// Exception thrown from resume when a coroutine stack is cancelled.
    24 // Should not have to be be sized (see trac #196).
    25 FORALL_DATA_EXCEPTION(CoroutineCancelled,
    26                 (dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) (
     24FORALL_DATA_EXCEPTION(CoroutineCancelled, (dtype coroutine_t), (coroutine_t)) (
    2725        coroutine_t * the_coroutine;
    2826        exception_t * the_exception;
     
    3028
    3129forall(dtype T)
    32 void mark_exception(CoroutineCancelled(T) *);
    33 
    34 forall(dtype T | sized(T))
    3530void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src);
    3631
     
    4237// Anything that implements this trait can be resumed.
    4338// Anything that is resumed is a coroutine.
    44 trait is_coroutine(dtype T | sized(T)
    45                 | is_resumption_exception(CoroutineCancelled(T))
    46                 | VTABLE_ASSERTION(CoroutineCancelled, (T))) {
     39trait is_coroutine(dtype T | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) {
    4740        void main(T & this);
    4841        $coroutine * get_coroutine(T & this);
  • libcfa/src/concurrency/invoke.h

    r33c3ded r223a633  
    9393
    9494        };
     95        // Wrapper for gdb
     96        struct cfathread_coroutine_t { struct $coroutine debug; };
    9597
    9698        static inline struct __stack_t * __get_stack( struct $coroutine * cor ) {
     
    129131                struct __condition_node_t * dtor_node;
    130132        };
     133        // Wrapper for gdb
     134        struct cfathread_monitor_t { struct $monitor debug; };
    131135
    132136        struct __monitor_group_t {
     
    186190                } node;
    187191
    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;
     192                #if defined( __CFA_WITH_VERIFY__ )
     193                        unsigned long long canary;
    198194                #endif
    199195        };
     196        // Wrapper for gdb
     197        struct cfathread_thread_t { struct $thread debug; };
    200198
    201199        #ifdef __CFA_DEBUG__
  • libcfa/src/concurrency/io.cfa

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

    r33c3ded r223a633  
    4747        #include "kernel/fwd.hfa"
    4848
    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
     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        ;
    8275
    8376        extern [* struct io_uring_sqe, __u32] __submit_alloc( struct __io_data & ring, __u64 data );
     
    347340        # CFA_HAVE_IORING_OP_MADVISE
    348341        Call('MADVISE', 'int madvise(void *addr, size_t length, int advice)', {
    349                 'addr': 'addr',
     342                'addr': '(__u64)addr',
    350343                'len': 'length',
    351344                'fadvise_advice': 'advice'
  • libcfa/src/concurrency/io/setup.cfa

    r33c3ded r223a633  
    147147        static void * iopoll_loop( __attribute__((unused)) void * args ) {
    148148                __processor_id_t id;
     149                id.full_proc = false;
    149150                id.id = doregister(&id);
    150151                __cfaabi_dbg_print_safe( "Kernel : IO poller thread starting\n" );
     
    246247                                        thrd.link.next = 0p;
    247248                                        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 __cfaabi_dbg_ctx2 );
     268                                unpark( &thrd );
    269269                        }
    270270                        else {
     
    275275                        }
    276276                } else {
    277                         unpark( &thrd __cfaabi_dbg_ctx2 );
     277                        unpark( &thrd );
    278278                }
    279279
  • libcfa/src/concurrency/kernel.cfa

    r33c3ded r223a633  
    237237        $coroutine * proc_cor = get_coroutine(this->runner);
    238238
    239         // Update global state
    240         kernelTLS.this_thread = thrd_dst;
    241 
    242239        // set state of processor coroutine to inactive
    243240        verify(proc_cor->state == Active);
     
    249246                thrd_dst->state = Active;
    250247
    251                 __cfaabi_dbg_debug_do(
    252                         thrd_dst->park_stale   = true;
    253                         thrd_dst->unpark_stale = true;
    254                 )
     248                // Update global state
     249                kernelTLS.this_thread = thrd_dst;
    255250
    256251                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    257252                /* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
     253                /* paranoid */ verify( thrd_dst->context.SP );
    258254                /* 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
    259255                /* 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
    260259
    261260                // set context switch to the thread that the processor is executing
    262                 verify( thrd_dst->context.SP );
    263261                __cfactx_switch( &proc_cor->context, &thrd_dst->context );
    264262                // when __cfactx_switch returns we are back in the processor coroutine
    265263
     264                /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_dst->canary );
    266265                /* 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 );
    267266                /* 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;
    271273
    272274                // We just finished running a thread, there are a few things that could have happened.
     
    286288                        // The thread has halted, it should never be scheduled/run again
    287289                        // We may need to wake someone up here since
    288                         unpark( this->destroyer __cfaabi_dbg_ctx2 );
     290                        unpark( this->destroyer );
    289291                        this->destroyer = 0p;
    290292                        break RUNNING;
     
    296298                // set state of processor coroutine to active and the thread to inactive
    297299                int old_ticket = __atomic_fetch_sub(&thrd_dst->ticket, 1, __ATOMIC_SEQ_CST);
    298                 __cfaabi_dbg_debug_do( thrd_dst->park_result = old_ticket; )
    299300                switch(old_ticket) {
    300301                        case 1:
     
    313314        // Just before returning to the processor, set the processor coroutine to active
    314315        proc_cor->state = Active;
    315         kernelTLS.this_thread = 0p;
    316316
    317317        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     
    334334                        __x87_store;
    335335                #endif
    336                 verify( proc_cor->context.SP );
     336                /* paranoid */ verify( proc_cor->context.SP );
     337                /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary );
    337338                __cfactx_switch( &thrd_src->context, &proc_cor->context );
     339                /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd_src->canary );
    338340                #if defined( __i386 ) || defined( __x86_64 )
    339341                        __x87_load;
     
    367369        /* paranoid */ #endif
    368370        /* paranoid */ verifyf( thrd->link.next == 0p, "Expected null got %p", thrd->link.next );
     371        /* paranoid */ verify( 0x0D15EA5E0D15EA5E == thrd->canary );
     372
    369373
    370374        if (thrd->preempted == __NO_PREEMPTION) thrd->state = Ready;
     
    403407
    404408// KERNEL ONLY unpark with out disabling interrupts
    405 void __unpark(  struct __processor_id_t * id, $thread * thrd __cfaabi_dbg_ctx_param2 ) {
    406         // record activity
    407         __cfaabi_dbg_record_thrd( *thrd, false, caller );
    408 
     409void __unpark(  struct __processor_id_t * id, $thread * thrd ) {
    409410        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 __cfaabi_dbg_ctx_param2 ) {
     428void unpark( $thread * thrd ) {
    429429        if( !thrd ) return;
    430430
    431431        disable_interrupts();
    432         __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd __cfaabi_dbg_ctx_fwd2 );
     432        __unpark( (__processor_id_t*)kernelTLS.this_processor, thrd );
    433433        enable_interrupts( __cfaabi_dbg_ctx );
    434434}
    435435
    436 void park( __cfaabi_dbg_ctx_param ) {
     436void park( void ) {
    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 );
    444441
    445442        returnToKernel();
     
    521518        disable_interrupts();
    522519                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    523                 bool ret = post( this->idle );
     520                post( this->idle );
    524521        enable_interrupts( __cfaabi_dbg_ctx );
    525522}
     
    649646                // atomically release spin lock and block
    650647                unlock( lock );
    651                 park( __cfaabi_dbg_ctx );
     648                park();
    652649                return true;
    653650        }
     
    670667
    671668        // make new owner
    672         unpark( thrd __cfaabi_dbg_ctx2 );
     669        unpark( thrd );
    673670
    674671        return thrd != 0p;
     
    681678        count += diff;
    682679        for(release) {
    683                 unpark( pop_head( waiting ) __cfaabi_dbg_ctx2 );
     680                unpark( pop_head( waiting ) );
    684681        }
    685682
     
    697694                        this.prev_thrd = kernelTLS.this_thread;
    698695                }
    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                 }
    710696        }
    711697)
  • libcfa/src/concurrency/kernel.hfa

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

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

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

    r33c3ded r223a633  
    6464
    6565// KERNEL ONLY unpark with out disabling interrupts
    66 void __unpark( struct __processor_id_t *, $thread * thrd __cfaabi_dbg_ctx_param2 );
     66void __unpark( struct __processor_id_t *, $thread * thrd );
    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 __cfaabi_dbg_ctx2 );
     79                                __unpark( id, expected );
    8080                                return true;
    8181                        }
  • libcfa/src/concurrency/monitor.cfa

    r33c3ded r223a633  
    122122
    123123                unlock( this->lock );
    124                 park( __cfaabi_dbg_ctx );
     124                park();
    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 __cfaabi_dbg_ctx2 );
     203                unpark( urgent->owner->waiting_thread );
    204204
    205205                // Park current thread waiting
    206                 park( __cfaabi_dbg_ctx );
     206                park();
    207207
    208208                // Some one was waiting for us, enter
     
    222222
    223223                // Park current thread waiting
    224                 park( __cfaabi_dbg_ctx );
     224                park();
    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 __cfaabi_dbg_ctx2 );
     266        unpark( new_owner );
    267267}
    268268
     
    493493        // Wake the threads
    494494        for(int i = 0; i < thread_count; i++) {
    495                 unpark( threads[i] __cfaabi_dbg_ctx2 );
     495                unpark( threads[i] );
    496496        }
    497497
    498498        // Everything is ready to go to sleep
    499         park( __cfaabi_dbg_ctx );
     499        park();
    500500
    501501        // We are back, restore the owners and recursions
     
    575575
    576576        // unpark the thread we signalled
    577         unpark( signallee __cfaabi_dbg_ctx2 );
     577        unpark( signallee );
    578578
    579579        //Everything is ready to go to sleep
    580         park( __cfaabi_dbg_ctx );
     580        park();
    581581
    582582
     
    679679
    680680                                // unpark the thread we signalled
    681                                 unpark( next __cfaabi_dbg_ctx2 );
     681                                unpark( next );
    682682
    683683                                //Everything is ready to go to sleep
    684                                 park( __cfaabi_dbg_ctx );
     684                                park();
    685685
    686686                                // We are back, restore the owners and recursions
     
    724724
    725725        //Everything is ready to go to sleep
    726         park( __cfaabi_dbg_ctx );
     726        park();
    727727
    728728
  • libcfa/src/concurrency/mutex.cfa

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

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

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

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

    r33c3ded r223a633  
    8888//----------
    8989// Park thread: block until corresponding call to unpark, won't block if unpark is already called
    90 void park( __cfaabi_dbg_ctx_param );
     90void park( void );
    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 __cfaabi_dbg_ctx_param2 );
     95void unpark( $thread * this );
    9696
    9797forall( dtype T | is_thread(T) )
    98 static inline void unpark( T & this __cfaabi_dbg_ctx_param2 ) { if(!&this) return; unpark( get_thread( this ) __cfaabi_dbg_ctx_fwd2 );}
     98static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );}
    9999
    100100//----------
  • libcfa/src/exception.h

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

    r33c3ded r223a633  
    9595// visible anywhere you use the instantiation of the exception is used.
    9696#define POLY_VTABLE_DECLARATION(exception_name, ...) \
    97         void mark_exception(exception_name(__VA_ARGS__) *); \
     97        VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable(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__, , ~)
    127136
    128137// All internal helper macros begin with an underscore.
     
    160169
    161170#define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \
    162         forall(_UNPACK assertions | VTABLE_ASSERTION(exception_name, parameters) ) \
     171        forall(_UNPACK assertions | \
     172                is_exception(exception_name parameters, VTABLE_TYPE(exception_name) parameters)) \
    163173        void ?{}(exception_name parameters & this)
    164174
    165175#define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \
    166176        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \
    167                 VTABLE_INIT(this, exception_name); \
     177                (this).virtual_table = &get_exception_vtable(&this); \
    168178        }
    169179
     
    185195#define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
    186196        struct exception_name; \
    187         void mark_exception(exception_name *); \
    188197        VTABLE_TYPE(exception_name); \
     198        VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *); \
    189199        extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
    190200        VTABLE_TYPE(exception_name) { \
     
    197207
    198208#define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
    199         void mark_exception(exception_name *) {} \
     209        VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *) { \
     210                return VTABLE_NAME(exception_name); \
     211        } \
    200212        void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
    201213                *this = *other; \
     
    218230
    219231#define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \
    220         void mark_exception(exception_name(__VA_ARGS__) *) {} \
     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        } \
    221237        void _GLUE2(exception_name,_copy)( \
    222238                        exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \
     
    227243                _GLUE2(exception_name,_copy), ^?{}, \
    228244                _CLOSE
     245
     246#define _IS_EXCEPTION(kind, exception_name, parameters, ...) \
     247        kind(exception_name parameters, VTABLE_TYPE(exception_name) parameters)
  • libcfa/src/parseargs.cfa

    r33c3ded r223a633  
    2525#include "limits.hfa"
    2626
    27 extern int cfa_args_argc;
    28 extern char ** cfa_args_argv;
    29 extern char ** cfa_args_envp;
     27extern int cfa_args_argc __attribute__((weak));
     28extern char ** cfa_args_argv __attribute__((weak));
     29extern char ** cfa_args_envp __attribute__((weak));
    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         parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, 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        }
    3541}
    3642
  • src/AST/Convert.cpp

    r33c3ded r223a633  
    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
    179194                auto decl = new FunctionDecl(
    180195                        node->name,
    181196                        Type::StorageClasses( node->storage.val ),
    182197                        LinkageSpec::Spec( node->linkage.val ),
    183                         get<FunctionType>().accept1( node->type ),
     198                        ftype,
     199                        //get<FunctionType>().accept1( node->type ),
    184200                        {},
    185201                        get<Attribute>().acceptL( node->attributes ),
     
    11521168
    11531169        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
    11541173                auto ty = new FunctionType {
    11551174                        cv( node ),
    11561175                        (bool)node->isVarArgs
    11571176                };
    1158                 ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
    1159                 ty->parameters = get<DeclarationWithType>().acceptL( node->params );
     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 );
    11601194                ty->forall = get<TypeDecl>().acceptL( node->forall );
    11611195                return visitType( node, ty );
     
    13741408        ast::Node * node = nullptr;
    13751409        /// cache of nodes that might be referenced by readonly<> for de-duplication
    1376         std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
     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 = {};
    13771415
    13781416        // Local Utilities:
     
    14471485                auto it = cache.find( old );
    14481486                if ( it == cache.end() ) return false;
    1449                 node = it->second;
     1487                node = const_cast<ast::Node *>(it->second.get());
    14501488                return true;
    14511489        }
     
    14861524        virtual void visit( const FunctionDecl * old ) override final {
    14871525                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
    14881544                auto decl = new ast::FunctionDecl{
    14891545                        old->location,
    14901546                        old->name,
    1491                         GET_ACCEPT_1(type, FunctionType),
     1547                        // GET_ACCEPT_1(type, FunctionType),
     1548                        std::move(paramVars),
     1549                        std::move(returnVars),
    14921550                        {},
    14931551                        { old->storageClasses.val },
     
    14961554                        { old->get_funcSpec().val }
    14971555                };
     1556
     1557                decl->type = ftype;
    14981558                cache.emplace( old, decl );
     1559
    14991560                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    15001561                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    25152576                        cv( old )
    25162577                };
    2517                 ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
    2518                 ty->params = GET_ACCEPT_V( parameters, DeclWithType );
     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                }
    25192588                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    25202589                visitType( old, ty );
  • src/AST/Decl.hpp

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

    r33c3ded r223a633  
    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
    3545        /// Substitute parameter/return type
    3646        std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) {
     
    4858                return n;
    4959        }
     60
     61        */
    5062};
    5163
  • src/AST/Pass.impl.hpp

    r33c3ded r223a633  
    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
    467471                                maybe_accept( node, &FunctionDecl::type );
    468472                                // function body needs to have the same scope as parameters - CompoundStmt will not enter
  • src/AST/SymbolTable.cpp

    r33c3ded r223a633  
    335335}
    336336
     337/*
    337338void SymbolTable::addFunctionType( const FunctionType * ftype ) {
    338339        addTypes( ftype->forall );
     
    340341        addIds( ftype->params );
    341342}
     343*/
    342344
    343345void SymbolTable::lazyInitScope() {
     
    368370                assert( ! params.empty() );
    369371                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    370                 const Type * base = InitTweak::getPointerBase( params.front()->get_type() );
     372                const Type * base = InitTweak::getPointerBase( params.front() );
    371373                assert( base );
    372374                return Mangle::mangle( base );
  • src/AST/SymbolTable.hpp

    r33c3ded r223a633  
    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

    r33c3ded r223a633  
    102102// --- FunctionType
    103103
     104
    104105FunctionType::FunctionType( const FunctionType & o )
    105106: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     
    112113
    113114namespace {
    114         bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) {
     115        bool containsTtype( const std::vector<ptr<Type>> & l ) {
    115116                if ( ! l.empty() ) {
    116                         return Tuples::isTtype( l.back()->get_type() );
     117                        return Tuples::isTtype( l.back() );
    117118                }
    118119                return false;
  • src/AST/Type.hpp

    r33c3ded r223a633  
    302302class FunctionType final : public ParameterizedType {
    303303public:
    304         std::vector<ptr<DeclWithType>> returns;
    305         std::vector<ptr<DeclWithType>> params;
     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;
    306309
    307310        /// Does the function accept a variable number of arguments following the arguments specified
  • src/Concurrency/Keywords.cc

    r33c3ded r223a633  
    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 ), vtable_name( getVTableName( exception_name ) ),
     68                  context_error( context_error ), exception_name( exception_name ),
     69                  vtable_name( getVTableName( exception_name ) ),
    6970                  needs_main( needs_main ), cast_target( cast_target ) {}
    7071
     
    8990                const std::string getter_name;
    9091                const std::string context_error;
     92                const std::string exception_name;
    9193                const std::string vtable_name;
    9294                bool needs_main;
     
    9597                StructDecl   * type_decl = nullptr;
    9698                FunctionDecl * dtor_decl = nullptr;
     99                StructDecl * except_decl = nullptr;
    97100                StructDecl * vtable_decl = nullptr;
    98101        };
     
    376379                else if ( is_target(decl) ) {
    377380                        handle( decl );
     381                }
     382                else if ( !except_decl && exception_name == decl->name && decl->body ) {
     383                        except_decl = decl;
    378384                }
    379385                else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
     
    398404                        assert( struct_type );
    399405
    400                         declsToAddAfter.push_back( Virtual::makeVtableInstance( vtable_decl, {
    401                                 new TypeExpr( struct_type->clone() ),
    402                         }, struct_type, nullptr ) );
     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                        ) );
    403413                }
    404414
     
    434444        void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
    435445                if ( vtable_decl ) {
    436                         declsToAddBefore.push_back( Virtual::makeVtableForward( vtable_decl, {
     446                        std::list< Expression * > poly_args = {
    437447                                new TypeExpr( new StructInstType( noQualifiers, decl ) ),
    438                         } ) );
     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 ) ) ) );
    439455                // Its only an error if we want a vtable and don't have one.
    440456                } else if ( ! vtable_name.empty() ) {
  • src/GenPoly/InstantiateGeneric.cc

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

    r33c3ded r223a633  
    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.
    114130                                initStatements.push_back( ctor );
    115131                                objDecl->init = nullptr;
  • src/InitTweak/InitTweak.cc

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

    r33c3ded r223a633  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun  9 20:26:55 2020
    13 // Update Count     : 1134
     12// Last Modified On : Thu Oct  8 08:03:38 2020
     13// Update Count     : 1135
    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

    r33c3ded r223a633  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Sat Feb 15 11:05:50 2020
    13  * Update Count     : 737
     12 * Last Modified On : Tue Oct  6 18:15:41 2020
     13 * Update Count     : 743
    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

    r33c3ded r223a633  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May 28 12:11:45 2020
    13 // Update Count     : 4500
     12// Last Modified On : Fri Oct  9 18:09:09 2020
     13// Update Count     : 4614
    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
    796795        | '(' VIRTUAL ')' cast_expression                                       // CFA
    797796                { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild< Expression >( $4 ), maybeMoveBuildType( nullptr ) ) ); }
     
    920919        | unary_expression assignment_operator assignment_expression
    921920                {
    922                         if ( $2 == OperKinds::AtAssn ) {
    923                                 SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
    924                         } else {
     921//                      if ( $2 == OperKinds::AtAssn ) {
     922//                              SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
     923//                      } else {
    925924                                $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );
    926                         } // if
     925//                      } // if
    927926                }
    928927        | unary_expression '=' '{' initializer_list_opt comma_opt '}'
     
    16761675
    16771676typedef_expression:
    1678                 // GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
     1677                // deprecated GCC, naming expression type: typedef name = exp; gives a name to the type of an expression
    16791678        TYPEDEF identifier '=' assignment_expression
    16801679                {
    1681                         // $$ = DeclarationNode::newName( 0 );                  // unimplemented
    1682                         SemanticError( yylloc, "Typedef expression is currently unimplemented." ); $$ = nullptr;
     1680                        SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    16831681                }
    16841682        | typedef_expression pop ',' push identifier '=' assignment_expression
    16851683                {
    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 //      ;
     1684                        SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     1685                }
     1686        ;
    17121687
    17131688c_declaration:
     
    17151690                { $$ = distAttr( $1, $2 ); }
    17161691        | typedef_declaration
    1717         | typedef_expression                                                            // GCC, naming expression type
     1692        | typedef_expression                                                            // deprecated GCC, naming expression type
    17181693        | sue_declaration_specifier
    17191694        ;
     
    20942069                { yyy = true; $$ = AggregateDecl::Union; }
    20952070        | EXCEPTION                                                                                     // CFA
    2096                 { yyy = true; $$ = AggregateDecl::Exception; }
     2071                // { yyy = true; $$ = AggregateDecl::Exception; }
     2072                { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
    20972073        ;
    20982074
     
    24362412// Overloading: function, data, and operator identifiers may be overloaded.
    24372413//
    2438 // Type declarations: "type" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
     2414// Type declarations: "otype" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
    24392415//     and incomplete types, and "ftype" is used for function types. Type declarations with initializers provide
    24402416//     definitions of new types. Type declarations with storage class "extern" provide opaque types.
     
    24652441        type_class identifier_or_type_name
    24662442                { typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
    2467           type_initializer_opt assertion_list_opt
     2443        type_initializer_opt assertion_list_opt
    24682444                { $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
    24692445        | type_specifier identifier_parameter_declarator
     
    24922468        assertion
    24932469        | assertion_list assertion
    2494                 { $$ = $1 ? $1->appendList( $2 ) : $2; }
     2470                { $$ = $1->appendList( $2 ); }
    24952471        ;
    24962472
  • src/ResolvExpr/CandidateFinder.cpp

    r33c3ded r223a633  
    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], paramType, symtab, cand->env, convCost ) );
    195                         convCost.decSpec( specCost( paramType ) );
     194                                        args[i], *param, symtab, cand->env, convCost ) );
     195                        convCost.decSpec( specCost( *param ) );
    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()->get_type();
     700                                const ast::Type * returnType = funcType->returns.front();
    701701                                if ( ! unify(
    702702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     
    712712                        std::size_t genStart = 0;
    713713
    714                         for ( const ast::DeclWithType * param : funcType->params ) {
    715                                 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
     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 ) {
    716730                                // Try adding the arguments corresponding to the current parameter to the existing
    717731                                // matches
     732                                // no default args for indirect calls
    718733                                if ( ! instantiateArgument(
    719                                         obj->type, obj->init, args, results, genStart, symtab ) ) return;
    720                         }
    721 
     734                                        param, nullptr, args, results, genStart, symtab ) ) return;
     735                        }
     736
     737                        endMatch:
    722738                        if ( funcType->isVarArgs ) {
    723739                                // append any unused arguments to vararg pack
  • src/ResolvExpr/CurrentObject.cc

    r33c3ded r223a633  
    594594        class SimpleIterator final : public MemberIterator {
    595595                CodeLocation location;
    596                 readonly< Type > type = nullptr;
     596                const 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                 readonly< ArrayType > array = nullptr;
    633                 readonly< Type > base = nullptr;
     632                const ArrayType * array = nullptr;
     633                const Type * base = nullptr;
    634634                size_t index = 0;
    635635                size_t size = 0;
  • src/ResolvExpr/ResolveAssertions.cc

    r33c3ded r223a633  
    277277                        const DeclarationWithType * candidate = cdata.id;
    278278
    279                         // build independent unification context for candidate
     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
    280287                        AssertionSet have, newNeed;
    281288                        TypeEnvironment newEnv{ resn.alt.env };
  • src/ResolvExpr/Resolver.cc

    r33c3ded r223a633  
    12231223                template<typename Iter>
    12241224                inline bool nextMutex( Iter & it, const Iter & end ) {
    1225                         while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
     1225                        while ( it != end && ! (*it)->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, paramType, resultEnv, need, have, open,
     1643                                                                                arg->expr->result, *param, resultEnv, need, have, open,
    16441644                                                                                symtab )
    16451645                                                                ) {
     
    16481648                                                                        ss << "candidate function not viable: no known conversion "
    16491649                                                                                "from '";
    1650                                                                         ast::print( ss, (*param)->get_type() );
     1650                                                                        ast::print( ss, *param );
    16511651                                                                        ss << "' to '";
    16521652                                                                        ast::print( ss, arg->expr->result );
  • src/ResolvExpr/SatisfyAssertions.cpp

    r33c3ded r223a633  
    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
    172179                        // build independent unification context for candidate
    173180                        ast::AssertionSet have, newNeed;
     
    318325                                        if ( ! func ) continue;
    319326
    320                                         for ( const ast::DeclWithType * param : func->params ) {
    321                                                 cost.decSpec( specCost( param->get_type() ) );
     327                                        for ( const auto & param : func->params ) {
     328                                                cost.decSpec( specCost( param ) );
    322329                                        }
    323330
  • src/ResolvExpr/SpecCost.cc

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

    r33c3ded r223a633  
    395395
    396396        template< typename Iterator1, typename Iterator2 >
    397         bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     397        bool unifyTypeList( 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 ( 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 ) ) {
     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 ) ) {
    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::DeclWithType > > flattenList(
    787                         const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
     786                static std::vector< ast::ptr< ast::Type > > flattenList(
     787                        const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    788788                ) {
    789                         std::vector< ast::ptr< ast::DeclWithType > > dst;
     789                        std::vector< ast::ptr< ast::Type > > dst;
    790790                        dst.reserve( src.size() );
    791                         for ( const ast::DeclWithType * d : src ) {
     791                        for ( const auto & 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::DeclWithType> dc = d->accept(expander);
    796                                 auto types = flatten( dc->get_type() );
     795                                ast::ptr<ast::Type> dc = d->accept(expander);
     796                                auto types = flatten( dc );
    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( new ast::ObjectDecl{ dc->location, "", t } );
     805                                        dst.emplace_back( t );
    806806                                }
    807807                        }
     
    811811                /// Creates a tuple type based on a list of DeclWithType
    812812                template< typename Iter >
    813                 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
     813                static ast::ptr< ast::Type > tupleFromTypes( 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)->get_type(), types );
     818                                flatten( *crnt, types );
    819819
    820820                                ++crnt;
     
    825825
    826826                template< typename Iter >
    827                 static bool unifyDeclList(
     827                static bool unifyTypeList(
    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)->get_type();
    834                                 const ast::Type * t2 = (*crnt2)->get_type();
     833                                const ast::Type * t1 = *crnt1;
     834                                const ast::Type * t2 = *crnt2;
    835835                                bool isTuple1 = Tuples::isTtype( t1 );
    836836                                bool isTuple2 = Tuples::isTtype( t2 );
     
    840840                                        // combine remainder of list2, then unify
    841841                                        return unifyExact(
    842                                                 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     842                                                t1, tupleFromTypes( 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                                                 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     847                                                tupleFromTypes( 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)->get_type();
     862                                const ast::Type * t1 = *crnt1;
    863863                                if ( ! Tuples::isTtype( t1 ) ) return false;
    864864                                return unifyExact(
    865                                         t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     865                                        t1, tupleFromTypes( 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)->get_type();
     869                                const ast::Type * t2 = *crnt2;
    870870                                if ( ! Tuples::isTtype( t2 ) ) return false;
    871871                                return unifyExact(
    872                                         tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     872                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    873873                                        noWiden(), symtab );
    874874                        }
     
    877877                }
    878878
    879                 static bool unifyDeclList(
    880                         const std::vector< ast::ptr< ast::DeclWithType > > & list1,
    881                         const std::vector< ast::ptr< ast::DeclWithType > > & list2,
     879                static bool unifyTypeList(
     880                        const std::vector< ast::ptr< ast::Type > > & list1,
     881                        const std::vector< ast::ptr< ast::Type > > & list2,
    882882                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    883883                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    884884                ) {
    885                         return unifyDeclList(
     885                        return unifyTypeList(
    886886                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    887887                                symtab );
     
    928928                        ) return;
    929929
    930                         if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
    931                         if ( ! unifyDeclList(
     930                        if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
     931                        if ( ! unifyTypeList(
    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]->get_type();
     1234                if ( func->returns.size() == 1 ) return func->returns[0];
    12351235
    12361236                std::vector<ast::ptr<ast::Type>> tys;
    1237                 for ( const ast::DeclWithType * decl : func->returns ) {
    1238                         tys.emplace_back( decl->get_type() );
     1237                for ( const auto & decl : func->returns ) {
     1238                        tys.emplace_back( decl );
    12391239                }
    12401240                return new ast::TupleType{ std::move(tys) };
  • src/SymTab/Autogen.cc

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

    r33c3ded r223a633  
    551551                        GuardValue( inFunctionType );
    552552                        inFunctionType = true;
    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 );
     553                        if (functionType->returns.empty()) mangleName << Encoding::void_t;
     554                        else accept_each( functionType->returns, *visitor );
    556555                        mangleName << "_";
    557                         std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
    558                         accept_each( paramTypes, *visitor );
     556                        accept_each( functionType->params, *visitor );
    559557                        mangleName << "_";
    560558                }
  • src/SymTab/Validate.cc

    r33c3ded r223a633  
    13841384        /// Replaces enum types by int, and function/array types in function parameter and return
    13851385        /// lists by appropriate pointers
     1386        /*
    13861387        struct EnumAndPointerDecay_new {
    13871388                const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
     
    14341435                }
    14351436        };
     1437        */
    14361438
    14371439        /// expand assertions from a trait instance, performing appropriate type variable substitutions
     
    18371839const ast::Type * validateType(
    18381840                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1839         ast::Pass< EnumAndPointerDecay_new > epc;
     1841        // ast::Pass< EnumAndPointerDecay_new > epc;
    18401842        ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    18411843        ast::Pass< ForallPointerDecay_new > fpd{ loc };
    18421844
    1843         return type->accept( epc )->accept( lrt )->accept( fpd );
     1845        return type->accept( lrt )->accept( fpd );
    18441846}
    18451847
  • src/SynTree/AggregateDecl.cc

    r33c3ded r223a633  
    2121#include "Common/utility.h"      // for printAll, cloneAll, deleteAll
    2222#include "Declaration.h"         // for AggregateDecl, TypeDecl, Declaration
     23#include "Expression.h"
    2324#include "Initializer.h"
    2425#include "LinkageSpec.h"         // for Spec, linkageName, Cforall
     
    8889const char * StructDecl::typeString() const { return aggrString( kind ); }
    8990
     91StructInstType * 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
     97StructInstType * 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
    90104const char * UnionDecl::typeString() const { return aggrString( Union ); }
    91105
  • src/SynTree/Declaration.h

    r33c3ded r223a633  
    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
    308312        virtual StructDecl * clone() const override { return new StructDecl( *this ); }
    309313        virtual void accept( Visitor & v ) override { v.visit( this ); }
  • src/SynTree/TypeDecl.cc

    r33c3ded r223a633  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 15:26:14 2019
    13 // Update Count     : 21
     12// Last Modified On : Thu Oct  8 18:18:55 2020
     13// Update Count     : 22
    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 ) : 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 ) :
     24        Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
    2425}
    2526
  • src/Virtual/Tables.cc

    r33c3ded r223a633  
    1414//
    1515
     16#include <SynTree/Attribute.h>
    1617#include <SynTree/Declaration.h>
    1718#include <SynTree/Expression.h>
     19#include <SynTree/Statement.h>
    1820#include <SynTree/Type.h>
    1921
     
    3840}
    3941
    40 // Fuse base polymorphic declaration and forall arguments into a new type.
    41 static 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 
    5042static ObjectDecl * makeVtableDeclaration(
    5143                StructInstType * type, Initializer * init ) {
     
    6658
    6759ObjectDecl * makeVtableForward( StructInstType * type ) {
     60        assert( type );
    6861        return makeVtableDeclaration( type, nullptr );
    6962}
    7063
    71 ObjectDecl * makeVtableForward(
    72                 StructDecl * polyDecl, std::list< Expression * > && parameters ) {
    73         return makeVtableForward( vtableInstType( polyDecl, std::move( parameters ) ) );
    74 }
    75 
    7664ObjectDecl * makeVtableInstance(
    77                 StructInstType * vtableType, Type * vobject_type, Initializer * init ) {
     65                StructInstType * vtableType, Type * objectType, Initializer * init ) {
     66        assert( vtableType );
     67        assert( objectType );
    7868        StructDecl * vtableStruct = vtableType->baseStruct;
    7969        // Build the initialization
     
    9282                                                new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
    9383                        } else if ( std::string( "size" ) == field->name ) {
    94                                 inits.push_back( new SingleInit( new SizeofExpr( vobject_type->clone() ) ) );
     84                                inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
    9585                        } else if ( std::string( "align" ) == field->name ) {
    96                                 inits.push_back( new SingleInit( new AlignofExpr( vobject_type->clone() ) ) );
     86                                inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
    9787                        } else {
    9888                                inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
     
    10898}
    10999
    110 ObjectDecl * makeVtableInstance(
    111                 StructDecl * polyDecl, std::list< Expression * > && parameters,
    112                 Type * vobject, Initializer * init ) {
    113         return makeVtableInstance(
    114                 vtableInstType( polyDecl, std::move( parameters ) ), vobject, init );
     100namespace {
     101        std::string const functionName = "get_exception_vtable";
     102}
     103
     104FunctionDecl * 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
     137FunctionDecl * 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;
    115147}
    116148
  • src/Virtual/Tables.h

    r33c3ded r223a633  
    2727bool isVTableInstanceName( std::string const & name );
    2828
    29 /// Converts exceptions into regular structures.
    30 //void ( std::list< Declaration * > & translationUnit );
    31 
    32 ObjectDecl * makeVtableForward( StructInstType * );
    33 ObjectDecl * 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.
     29ObjectDecl * makeVtableForward( StructInstType * vtableType );
     30/* Create a forward declaration of a vtable of the given type.
     31 * vtableType node is consumed.
    3832 */
    3933
    40 ObjectDecl * makeVtableInstance( StructInstType *, Type *, Initializer * );
    41 ObjectDecl * makeVtableInstance(
    42         StructDecl *, std::list< Expression * > &&, Type *, Initializer * );
     34ObjectDecl * makeVtableInstance( StructInstType * vtableType, Type * objectType,
     35        Initializer * init = nullptr );
    4336/* Create an initialized definition of a vtable.
    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.
     37 * vtableType and init (if provided) nodes are consumed.
     38 */
     39
     40// Some special code for how exceptions interact with virtual tables.
     41FunctionDecl * 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
     46FunctionDecl * makeGetExceptionFunction(
     47        ObjectDecl * vtableInstance, Type * exceptType );
     48/* Create the definition of the exception virtual function.
     49 * exceptType node is consumed.
    5050 */
    5151
  • src/main.cc

    r33c3ded r223a633  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 19 12:03:00 2020
    13 // Update Count     : 634
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Thu Oct  8 18:17:46 2020
     13// Update Count     : 637
    1414//
    1515
     
    451451
    452452
    453 static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
     453static const char optstring[] = ":c:ghlLmNnpdOAP: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         "don't print output that isn't deterministic",        // -d
    490         "Use the old-ast",                                    // -O
    491         "Use the new-ast",                                    // -A
    492         "print",                                              // -P
     489        "only print deterministic output",                  // -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

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

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

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

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

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

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

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

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

    r33c3ded r223a633  
    1 error: No reasonable alternatives for expression Untyped Init Expression
    2   Name: rx  InitAlternative: reference to signed int
    3 error: No reasonable alternatives for expression Untyped Init Expression
    4   Name: px  InitAlternative: pointer to signed int
    5 error: No reasonable alternatives for expression Untyped Init Expression
    6   Name: crx  InitAlternative: reference to float
    7 error: No reasonable alternatives for expression Untyped Init Expression
    8   Name: cpx  InitAlternative: pointer to float
    9 init1.cfa:94:1 error: No reasonable alternatives for expression Generated Cast of:
    10   Name: rx
    11 ... to:
    12   reference to signed int
    13 init1.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 
    22 init1.cfa:104:1 error: No reasonable alternatives for expression Generated Cast of:
    23   Name: crx
    24 ... to:
    25   reference to float
    26 init1.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 
    35 init1.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)
    39 init1.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 
     1init1.cfa: In function '_X4mainFi___1':
     2init1.cfa:136:9: note: #pragma message: Compiled
  • tests/.expect/labelledExit.txt

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

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

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

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

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

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

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

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

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

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

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

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

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

    r33c3ded r223a633  
     1done
  • tests/Makefile.am

    r33c3ded r223a633  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Tue Nov 20 11:18:51 2018
    14 ## Update Count     : 68
     13## Last Modified On : Fri Oct  9 23:13:07 2020
     14## Update Count     : 86
    1515###############################################################################
    1616
     
    4040        -fdebug-prefix-map=$(abspath ${abs_srcdir})= \
    4141        -fdebug-prefix-map=/tmp= \
     42        -fno-diagnostics-show-caret \
    4243        -g \
    4344        -Wall \
     
    5253
    5354# adjust CC to current flags
    54 CC = $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
     55CC = LC_ALL=C $(if $(DISTCC_CFA_PATH),distcc $(DISTCC_CFA_PATH) ${ARCH_FLAGS},$(TARGET_CFA) ${DEBUG_FLAGS} ${ARCH_FLAGS})
    5556CFACC = $(CC)
    5657
     
    133134        $(CFACOMPILETEST) -CFA -XCFA -p -c -fsyntax-only -o $(abspath ${@})
    134135
    135 # Use for tests where the make command is expected to succeed but the expected.txt should be compared to stderr
    136 EXPECT_STDERR = builtins/sync warnings/self-assignment
    137 $(EXPECT_STDERR): % : %.cfa $(CFACCBIN)
    138         $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})
    139 
    140136#------------------------------------------------------------------------------
    141137# CUSTOM TARGET
    142138#------------------------------------------------------------------------------
    143 # tests that just validate syntax
    144 expression : expression.cfa $(CFACCBIN)
    145         $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})
     139# tests that just validate syntax and compiler output should be compared to stderr
     140CFACOMPILE_SYNTAX = $(CFACOMPILETEST) -Wno-unused-variable -Wno-unused-label -c -fsyntax-only -o $(abspath ${@})
     141
     142SYNTAX_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 ${@}), )
    146147
    147148# expected failures
    148 # use custom target since they require a custom define and custom dependencies
     149# use custom target since they require a custom define *and* have a name that doesn't match the file
    149150alloc-ERROR : alloc.cfa $(CFACCBIN)
    150         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     151        $(CFACOMPILE_SYNTAX) -DERR1
     152        -cp $(test) $(abspath ${@})
     153
     154init1-ERROR : init1.cfa $(CFACCBIN)
     155        $(CFACOMPILE_SYNTAX) -DERR1
     156        -cp $(test) $(abspath ${@})
    151157
    152158typedefRedef-ERR1 : typedefRedef.cfa $(CFACCBIN)
    153         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     159        $(CFACOMPILE_SYNTAX) -DERR1
     160        -cp $(test) $(abspath ${@})
    154161
    155162nested-types-ERR1 : nested-types.cfa $(CFACCBIN)
    156         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     163        $(CFACOMPILE_SYNTAX) -DERR1
     164        -cp $(test) $(abspath ${@})
    157165
    158166nested-types-ERR2 : nested-types.cfa $(CFACCBIN)
    159         $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@})
     167        $(CFACOMPILE_SYNTAX) -DERR2
     168        -cp $(test) $(abspath ${@})
    160169
    161170raii/memberCtors-ERR1 : raii/memberCtors.cfa $(CFACCBIN)
    162         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     171        $(CFACOMPILE_SYNTAX) -DERR1
     172        -cp $(test) $(abspath ${@})
    163173
    164174raii/ctor-autogen-ERR1 : raii/ctor-autogen.cfa $(CFACCBIN)
    165         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     175        $(CFACOMPILE_SYNTAX) -DERR1
     176        -cp $(test) $(abspath ${@})
    166177
    167178raii/dtor-early-exit-ERR1 : raii/dtor-early-exit.cfa $(CFACCBIN)
    168         $(CFACOMPILETEST) -DERR1 -c -fsyntax-only -o $(abspath ${@})
     179        $(CFACOMPILE_SYNTAX) -DERR1
     180        -cp $(test) $(abspath ${@})
    169181
    170182raii/dtor-early-exit-ERR2 : raii/dtor-early-exit.cfa $(CFACCBIN)
    171         $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@})
     183        $(CFACOMPILE_SYNTAX) -DERR2
     184        -cp $(test) $(abspath ${@})
    172185
    173186# Exception Tests
  • tests/alloc.cfa

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

    r33c3ded r223a633  
    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 : Tue Feb 19 21:18:46 2019
    14 // Update Count     : 1
    15 // 
     13// Last Modified On : Sun Sep 27 09:05:40 2020
     14// Update Count     : 4
     15//
    1616
    17 int a1[];
     17int a1[0];
    1818//int a2[*];
    1919//double a4[3.0];
    2020
    21 int m1[][3];
     21int m1[0][3];
    2222//int m2[*][*];
    2323int m4[3][3];
     
    4949}
    5050
    51 int main() {}
     51int main() {
     52        #if !defined(NO_COMPILED_PRAGMA)
     53                #pragma message( "Compiled" )   // force non-empty .expect file
     54        #endif
     55}
    5256
    5357// Local Variables: //
  • tests/builtins/.expect/sync.txt

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

    r33c3ded r223a633  
    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); }
    6968        #endif
    7069
     
    355354
    356355int main() {
    357         return 0;
     356        #pragma message( "Compiled" )                   // force non-empty .expect file
    358357}
  • tests/cast.cfa

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

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

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

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

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

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

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

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

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

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

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

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

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

    r33c3ded r223a633  
    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 _110_0_T (not function type)
     135          instance of type _110_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 _110_0_T (not function type)
    138138          ... with attributes:
    139139            Attribute with name: unused
  • tests/errors/.expect/completeType.x86.txt

    r33c3ded r223a633  
    132132?=?: pointer to function
    133133        ... with parameters
    134           reference to instance of type _108_0_T (not function type)
    135           instance of type _108_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 _108_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/exceptions/.expect/virtual-cast.txt

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

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

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

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

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

    r33c3ded r223a633  
    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;
     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
    8589} // main
  • tests/forall.cfa

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

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

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

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

    r33c3ded r223a633  
    99// Author           : Michael Brooks
    1010// Created On       : Thu Jul 16 22:00:00 2020
    11 // Last Modified By : Michael Brooks
    12 // Last Modified On : Thu Jul 16 22:00:00 2020
    13 // Update Count     : 1
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun Oct 11 10:26:50 2020
     13// Update Count     : 8
    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
    4350    //
    4451    // unsound initializations
    4552    //
    4653
     54    #ifdef ERR1
    4755    // mismatched referenced type
    4856    int & ry = rx;
     
    5260    float & ry2 = crx;
    5361    float * py2 = cpx;
     62    #endif // ERR1
    5463}
    5564
     
    9099//
    91100
     101#ifdef ERR1
    92102int & f_ry() {
    93103    float & rx = *0p;
     
    119129    return s;               // mismatched referenced type
    120130}
     131#endif // ERR1
     132
     133int main() {
     134    #pragma message( "Compiled" )                       // force non-empty .expect file
     135}
  • tests/labelledExit.cfa

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

    r33c3ded r223a633  
    1010// Created On       : Tue May 10 20:44:20 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 17:57:55 2018
    13 // Update Count     : 8
     12// Last Modified On : Sun Sep 27 08:45:43 2020
     13// Update Count     : 10
    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.
    1518
    1619#include <limits.hfa>
     
    147150
    148151int main(int argc, char const *argv[]) {
    149         //DUMMY
    150         return 0;
     152        #pragma message( "Compiled" )                                           // force non-empty .expect file
    151153}
    152154
  • tests/maybe.cfa

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

    r33c3ded r223a633  
    1010// Created On       : Mon Jul 9 10:20:03 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb 12 18:21:15 2020
    13 // Update Count     : 3
     12// Last Modified On : Sun Sep 27 08:48:59 2020
     13// Update Count     : 6
    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.
     98        // A.N(int) x;  // xxx - should not be an error, but currently is.
     99
     100        #pragma message( "Compiled" )                   // force non-empty .expect file
    99101}
    100102
  • tests/numericConstants.cfa

    r33c3ded r223a633  
    1010// Created On       : Wed May 24 22:10:36 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  5 08:58:16 2019
    13 // Update Count     : 5
     12// Last Modified On : Sun Sep 27 07:55:22 2020
     13// Update Count     : 7
    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
    6567} // main
    6668
  • tests/operators.cfa

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

    r33c3ded r223a633  
    8888                raise
    8989
     90def 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
    9099def is_ascii(fname):
    91100        if settings.dry_run:
    92101                print("is_ascii: %s" % fname)
    93                 return True
     102                return (True, "")
    94103
    95104        if not os.path.isfile(fname):
    96                 return False
    97 
    98         code, out = sh("file %s" % fname, output_file=subprocess.PIPE)
     105                return (False, "No file")
     106
     107        code, out = sh("file", fname, output_file=subprocess.PIPE)
    99108        if code != 0:
    100                 return False
     109                return (False, "'file EXPECT' failed with code {}".format(code))
    101110
    102111        match = re.search(".*: (.*)", out)
    103112
    104113        if not match:
    105                 return False
    106 
    107         return match.group(1).startswith("ASCII text")
     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)))
    108120
    109121def is_exe(fname):
  • tests/raii/.expect/ctor-autogen.txt

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

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

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

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

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

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

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

    r33c3ded r223a633  
    173173        test.prepare()
    174174
     175        # ----------
     176        # MAKE
     177        # ----------
    175178        # build, skipping to next test on error
    176179        with Timed() as comp_dur:
    177180                make_ret, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file )
    178181
     182        # ----------
     183        # RUN
     184        # ----------
     185        # run everything in a temp directory to make sure core file are handled properly
    179186        run_dur = None
    180         # run everything in a temp directory to make sure core file are handled properly
    181187        with tempdir():
    182188                # if the make command succeeds continue otherwise skip to diff
     
    256262        make('clean', output_file=subprocess.DEVNULL, error=subprocess.DEVNULL)
    257263
    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)
     264        # create the executor for our jobs
     265        pool = multiprocessing.Pool(jobs)
    267266
    268267        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)
    274268
    275269        # for each test to run
     
    360354                failed = 0
    361355
     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

    r33c3ded r223a633  
    2727typedef int ARR[];
    2828typedef int ARR[];
    29 // #ifdef ERR1
    30 // if a typedef has an array dimension,
    31 // it can only be redefined to the same dimension
     29#ifdef ERR1
     30// if a typedef has an array dimension, it can only be redefined to the same dimension
    3231typedef int ARR[2];
    33 // #endif
     32#endif
    3433
    3534typedef int X;
     
    5453
    5554int main() {
    56   typedef int ARR[sz];
     55        typedef int ARR[sz];
    5756
    58   // can't redefine typedef which is VLA
     57        // can't redefine typedef which is VLA
    5958#if ERR1
    60   typedef int ARR[sz];
     59        typedef int ARR[sz];
    6160#endif
    6261
    63   Foo *x;
     62        Foo * x;
    6463
    65   typedef struct Bar Foo;
    66   Foo *y;
     64        typedef struct Bar Foo;
     65        Foo * y;
    6766
    68   typedef int *** pt;
     67        typedef int *** pt;
     68
     69        #pragma message( "Compiled" )                   // force non-empty .expect file
    6970}
  • tests/typeof.cfa

    r33c3ded r223a633  
    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
     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
    1112}
  • tests/variableDeclarator.cfa

    r33c3ded r223a633  
    1010// Created On       : Wed Aug 17 08:41:42 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Nov  6 18:02:16 2018
    13 // Update Count     : 2
     12// Last Modified On : Sun Sep 27 07:46:17 2020
     13// Update Count     : 13
    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[];
     35int f15[0];
    3636int f16[10];
    37 int (f17[]);
     37int (f17[0]);
    3838int (f18[10]);
    3939
    40 int *f19[];
    41 int *f20[10];
    42 int **f21[];
    43 int **f22[10];
    44 int * const *f23[];
    45 int * const *f24[10];
    46 int * const * const f25[];
     40int * f19[0];
     41int * f20[10];
     42int ** f21[0];
     43int ** f22[10];
     44int * const * f23[0];
     45int * const * f24[10];
     46int * const * const f25[0];
    4747int * const * const f26[10];
    4848
    49 int *(f27[]);
     49int *(f27[0]);
    5050int *(f28[10]);
    51 int **(f29[]);
     51int **(f29[0]);
    5252int **(f30[10]);
    53 int * const *(f31[]);
     53int * const *(f31[0]);
    5454int * const *(f32[10]);
    55 int * const * const (f33[]);
     55int * const * const (f33[0]);
    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[][3];
     67int f43[0][3];
    6868int f44[3][3];
    69 int (f45[])[3];
     69int (f45[0])[3];
    7070int (f46[3])[3];
    71 int ((f47[]))[3];
     71int ((f47[0]))[3];
    7272int ((f48[3]))[3];
    7373
    74 int *f49[][3];
    75 int *f50[3][3];
    76 int **f51[][3];
    77 int **f52[3][3];
    78 int * const *f53[][3];
    79 int * const *f54[3][3];
    80 int * const * const f55[][3];
     74int * f49[0][3];
     75int * f50[3][3];
     76int ** f51[0][3];
     77int ** f52[3][3];
     78int * const * f53[0][3];
     79int * const * f54[3][3];
     80int * const * const f55[0][3];
    8181int * const * const f56[3][3];
    8282
    83 int (*f57[][3]);
    84 int (*f58[3][3]);
    85 int (**f59[][3]);
    86 int (**f60[3][3]);
    87 int (* const *f61[][3]);
    88 int (* const *f62[3][3]);
    89 int (* const * const f63[][3]);
     83int (* f57[0][3]);
     84int (* f58[3][3]);
     85int (** f59[0][3]);
     86int (** f60[3][3]);
     87int (* const * f61[0][3]);
     88int (* const * f62[3][3]);
     89int (* const * const f63[0][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__
    124125// Cforall extensions
    125126
     
    129130const * const * int cf6;
    130131
    131 [] int cf15;
     132[0] int cf15;
    132133[10] int cf16;
    133134
    134 [] * int cf19;
     135[0] * int cf19;
    135136[10] * int cf20;
    136 int **cf21[];
     137int ** cf21[0];
    137138[10] * * int cf22;
    138 [] * const * int cf23;
     139[0] * const * int cf23;
    139140[10] * const * int cf24;
    140 [] const * const * int cf25;
     141[0] const * const * int cf25;
    141142[10] const * const * int cf26;
    142143
     
    150151const * const * [10] int cf42;
    151152
    152 [][3] int cf43;
     153[0][3] int cf43;
    153154[3][3] int cf44;
    154155
    155 [][3] * int cf49;
     156[0][3] * int cf49;
    156157[3][3] * int cf50;
    157 [][3] * * int cf51;
     158[0][3] * * int cf51;
    158159[3][3] * * int cf52;
    159 [][3] const * int cf53;
     160[0][3] const * int cf53;
    160161[3][3] * const * int cf54;
    161 [][3] const * const * int cf55;
     162[0][3] const * const * int cf55;
    162163[3][3] const * const * int cf56;
    163164
     
    173174
    174175*[]*[]* [ *[]*[] int ]( *[]*[] int, *[]*[] int ) v3;
     176#endif // __CFA__
    175177
    176178//Dummy main
    177 int main(int argc, char const *argv[])
    178 {
    179         return 0;
     179int main( int argc, char const * argv[] ) {
     180        #pragma message( "Compiled" )                                           // force non-empty .expect file
    180181}
    181182
  • tests/voidPtr.cfa

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

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

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

    r33c3ded r223a633  
    5353// C useless declarations
    5454
     55#ifdef ERROR
    5556        int;
    5657        TD;
     
    7071        W(int);
    7172        W(int).X;
     73#endif // ERROR
    7274};
    7375
  • tools/gdb/utils-gdb.py

    r33c3ded r223a633  
    4444STACK = []
    4545
    46 # A global variable to keep all system task name
    47 SysTask_Name = ["uLocalDebuggerReader", "uLocalDebugger", "uProcessorTask", "uBootTask", "uSystemTask",
    48 "uProcessorTask", "uPthread", "uProfiler"]
    49 
    5046not_supported_error_msg = "Not a supported command for this language"
    5147
     
    10197        return cluster_root
    10298
     99def 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
     108def 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
     128def 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
     149def 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
     160def tls_for_proc(proc):
     161        return tls_for_pthread(proc['_X13kernel_threadm_1'])
     162
     163def thread_for_pthread(pthrd):
     164        return tls_for_pthread(pthrd)['_X11this_threadVPS7$thread_1']
     165
     166def thread_for_proc(proc):
     167        return tls_for_proc(proc)['_X11this_threadVPS7$thread_1']
     168
     169
     170
    103171def find_curr_thread():
    104172        # btstr = gdb.execute('bt', to_string = True).splitlines()
     
    108176        # return btstr[0].split('this=',1)[1].split(',')[0].split(')')[0]
    109177        return None
    110 
    111 def 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 
    131178
    132179def lookup_cluster(name = None):
     
    239286        """Cforall: Display currently known processors
    240287Usage:
    241         info processors                 : print out all the processors in the Main Cluster
    242         info processors all             : print out all processors in all clusters
     288        info processors                 : print out all the processors
    243289        info processors <cluster_name>  : print out all processors in a given cluster
    244290"""
     
    247293                super(Processors, self).__init__('info processors', gdb.COMMAND_USER)
    248294
    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']
     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:
    262303                        stop_count  = processor['_X10terminatedS9semaphore_1']['_X5counti_1']
    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
     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))
    277322
    278323        #entry point from gdb
     
    282327
    283328                if not arg:
    284                         clusters = [lookup_cluster(None)]
    285                 elif arg == "all":
    286329                        clusters = all_clusters()
    287330                else:
     
    292335                        return
    293336
    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")
     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)
    314352
    315353                print()
Note: See TracChangeset for help on using the changeset viewer.