Changes in / [7d0a3ba:358cba0]


Ignore:
Files:
14 added
15 deleted
36 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    r7d0a3ba r358cba0  
    260260                def install_dir = pwd tmp: true
    261261
     262                //Output compiler version to help with debug
     263                echo """C++ Compiler :"""
     264                sh "which ${compiler.cpp_cc} && ${compiler.cpp_cc} --version"
     265                echo """C   Compiler :"""
     266                sh "which ${compiler.cfa_cc} && ${compiler.cfa_cc} --version"
     267
    262268                //Configure the conpilation (Output is not relevant)
    263                 //Use the current directory as the installation target so nothing
    264                 //escapes the sandbox
     269                //Use the current directory as the installation target so nothing escapes the sandbox
    265270                //Also specify the compiler by hand
    266271                sh "./configure CXX=${compiler.cpp_cc} ${architecture} --with-backend-compiler=${compiler.cfa_cc} --prefix=${install_dir} --enable-silent-rules --quiet"
  • doc/bibliography/pl.bib

    r7d0a3ba r358cba0  
    782782    howpublished= {\href{http://www.boost.org/doc/libs/1_61_0/libs/coroutine/doc/html/index.html}
    783783                  {{http://www.boost.org/\-doc/\-libs/1\_61\_0/\-libs/\-coroutine/\-doc/\-html/\-index.html}}},
    784     note        = {Accessed: 2016-09},
     784    optnote     = {Accessed: 2016-09},
    785785}
    786786
     
    855855    keywords    = {ANSI C 89},
    856856    contributer = {gjditchfield@plg},
    857     title       = {American National Standard for Information Systems -- Programming Language -- {C}},
     857    author      = {C90},
     858    title       = {Programming Languages -- {C}},
    858859    organization= {American National Standards Institute},
    859     address     = {1430 Broadway, New York, New York  10018},
    860     month       = dec,
    861     year        = 1989,
    862     note        = {X3.159-1989}
     860    address     = {New York, NY, U.S.A.},
     861    year        = 1990,
     862    note        = {ANSI/ISO 9899-1990}
    863863}
    864864
     
    888888    title       = {\textsf{C}{$\mathbf{\forall}$} Features},
    889889    howpublished= {\url{https://plg.uwaterloo.ca/~cforall/features}},
    890     note        = {Accessed: 2018-01-01},
     890    optnote     = {Accessed: 2018-01-01},
    891891}
    892892
     
    900900    address     = {Waterloo, Ontario, Canada, N2L 3G1},
    901901    note        = {\href{http://plg.uwaterloo.ca/theses/EstevesThesis.pdf}{http://\-plg.uwaterloo.ca/\-theses/\-EstevesThesis.pdf}},
     902}
     903
     904@misc{CFAStackEvaluation,
     905    author      = {Aaron Moss},
     906    title       = {\textsf{C}$\mathbf{\forall}$ Stack Evaluation Programs},
     907    year        = 2018,
     908    howpublished= {\href{https://plg.uwaterloo.ca/~cforall/evaluation.zip}{https://plg.uwaterloo.ca/\-\-$\sim$cforall/\-StackEvaluation.zip}},
     909    optnote     = {[Accessed May 2018]},
    902910}
    903911
     
    16401648}
    16411649
     1650@misc{Taylor10,
     1651    keywords    = {const, poisoning},
     1652    contributer = {pabuhr@plg},
     1653    author      = {Ian Lance Taylor},
     1654    title       = {const},
     1655    month       = oct,
     1656    year        = 2010,
     1657    howpublished= {\href{https://www.airs.com/blog/archives/428}
     1658                  {https://www.airs.com/\-blog/\-archives/\-428}},
     1659    optnote     = {Accessed: 2018-05},
     1660}
     1661
    16421662@phdthesis{Ditchfield92,
    16431663    keywords    = {C, parametric polymorphism, overloading},
     
    27552775@misc{GCCExtensions,
    27562776    contributer = {a3moss@uwaterloo.ca},
    2757     key         = {{GNU}},
     2777    key         = {C Extensions},
    27582778    author      = {{C Extensions}},
    27592779    title       = {Extensions to the {C} Language Family},
    27602780    year        = 2014,
    27612781    howpublished= {\href{https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/C-Extensions.html}{https://\-gcc.gnu.org/\-onlinedocs/\-gcc-4.7.2/\-gcc/\-C\-Extensions.html}},
    2762     note        = {Accessed: 2017-04-02},
     2782    optnote     = {Accessed: 2017-04-02},
    27632783}
    27642784
     
    29472967    month       = jul, year = 1987,
    29482968    volume      = 4, number = 4, pages = {9-16}
     2969}
     2970
     2971@misc{Sutter05c,
     2972    contributer = {pabuhr@plg},
     2973    title       = {The Free Lunch Is Over: A Fundamental Turn Toward Concurrency in Software},
     2974    author      = {Herb Sutter},
     2975    howpublished= {\url{http://www.gotw.ca/publications/concurrency-ddj.htm}},
     2976    year        = {2005},
     2977    note        = {originally Dr. Dobb's Journal 30(3)},
    29492978}
    29502979
     
    31373166    year        = 2014,
    31383167    howpublished= {https://developer.gnome.org/gobject/stable/},
    3139     note        = {Accessed: 2017-04},
     3168    optnote     = {Accessed: 2017-04},
    31403169}
    31413170
     
    32093238
    32103239% H
     3240
     3241@manual{Haskell10,
     3242    keywords    = {Haskell},
     3243    contributer = {pabuhr@plg},
     3244    author      = {Haskell},
     3245    title       = {Haskell 2010 Language Report},
     3246    edition     = {{S}imon {M}arlow},
     3247    year        = 2010,
     3248    note        = {\href{https://haskell.org/definition/haskell2010.pdf}{https://haskell.org/\-definition/\-haskell2010.pdf}},
     3249}
    32113250
    32123251@article{Michael04a,
     
    37603799    keywords    = {concurrency, critical section},
    37613800    contributer = {pabuhr@plg},
    3762     author      = {Dominic Duggan and Gordon V. Cormack and John Ophel},
     3801    author      = {Dominic Duggan and G. V. Cormack and John Ophel},
    37633802    title       = {Kinded Type Inference for Parametric Overloading},
    37643803    journal     = acta,
     
    46854724    year        = 2015,
    46864725    howpublished= {\href{https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/ObjectiveC.html}{https://developer.apple.com/\-library/\-content/\-documentation/\-General/\-Conceptual/\-DevPedia-\-CocoaCore/\-ObjectiveC.html}},
    4687     note        = {Accessed: 2018-03}
     4726    optnote     = {Accessed: 2018-03}
    46884727}
    46894728
     
    46954734    year        = 2015,
    46964735    howpublished= {\href{https://developer.apple.com/library/content/documentation/Xcode/Conceptual/RN-Xcode-Archive/Chapters/xc7_release_notes.html}{https://developer.apple.com/\-library/\-content/\-documentation/\-Xcode/\-Conceptual/\-RN-Xcode-Archive/\-Chapters/\-xc7\_release\_notes.html}},
    4697     note        = {Accessed: 2017-04}
     4736    optnote     = {Accessed: 2017-04}
    46984737}
    46994738
     
    57575796    keywords    = {Cyclone, existential types, polymorphism, type variables},
    57585797    contributer = {a3moss@plg},
    5759     author      = {Dan Grossman},
     5798    author      = {D. Grossman},
    57605799    title       = {Quantified Types in an Imperative Language},
    57615800    journal     = toplas,
     
    67626801    title       = {{TIOBE} Index},
    67636802    howpublished= {\href{http://www.tiobe.com/tiobe_index}{http://\-www.tiobe.com/\-tiobe\_index}},
    6764     note        = {Accessed: 2018-09},
     6803    optnote     = {Accessed: 2018-09},
    67656804}
    67666805
     
    70877126    year        = 2017,
    70887127    howpublished= {\url{https://wiki.gnome.org/Projects/Vala/Manual}},
    7089     note        = {Accessed: 2017-04}
     7128    optnote     = {Accessed: 2017-04}
    70907129}
    70917130
  • doc/papers/AMA/AMA-stix/Documents/README.txt

    r7d0a3ba r358cba0  
    1313%   NJDnatbib.sty --> NJD natbib reference package.
    1414%   Stix-Fonts (folder) -->   Stix font files
    15 
    16 %   MiKTeX 2.9 (Freeware software) is required to install STIX/LATO fonts
    17 %   Download MiKTeX installer & instructions from the below URLs
    18         https://miktex.org/download
    19         Instructions to install the basic MiKTeX installer
    20         https://miktex.org/howto/install-miktex
    21 
    22 %   Execute(double click) --> Windows-Stix-fontinstaller.exe from Stix-Fonts folder (This EXE file will install fonts to local drive) (please rename Windows-Stix-fontinstaller.e_xe to Windows-Stix-fontinstaller.exe)
     15%   Execute(double click) --> Windows-Stix-fontinstaller.exe from Stix-Fonts folder (This EXE file will install fonts to local drive)
    2316%   Still shows font error, please do the following
    2417%   Start-->run--> type "mo_edmin.exe" and press enter
  • doc/papers/AMA/AMA-stix/ama/WileyNJD-AMA.bst

    r7d0a3ba r358cba0  
    502502      editor empty$
    503503      { booktitle emphasize * }
    504       { " " * format.editors * " " * booktitle emphasize * ", " * }
     504    { " " * format.editors * " " * booktitle emphasize * ", " * }
    505505      if$
    506506    }
     
    691691    { format.journal emphasize "journal" output.check
    692692      format.date add.semicolon "year" output.check
     693      blank.sep
    693694      format.volume output
    694695      format.number output
     
    824825      new.block
    825826      format.pages output
     827      new.block
    826828      organization output
     829      new.block
    827830      publisher output
    828831      inproformat.date "year" output.check
     
    863866    { new.block organization new.block address new.block.checkb
    864867      organization output
     868      new.block
    865869      address output
    866870    }
     
    883887  new.block
    884888  school "school" output.check
     889  new.block
    885890  address output
    886891  format.date "year" output.check
     
    927932  "PhD thesis" format.thesis.type output.nonnull
    928933  school "school" output.check
     934  new.block
    929935  address output
    930936  format.date "year" output.check
  • doc/papers/AMA/AMA-stix/ama/WileyNJD-v2.cls

    r7d0a3ba r358cba0  
    484484\if@STIXLargeOneCol%
    485485\RequirePackage[not1,notextcomp,lcgreekalpha]{stix}%
    486 %\usepackage[scaled]{helvet}
    487 %\renewcommand\familydefault{\sfdefault}
    488486\usepackage[T1]{fontenc}
    489487\BXhsize=170mm%
     
    528526%\RequirePackage[not1,notextcomp,lcgreekalpha]{stix}%
    529527
    530 \captionsetup[figure]{labelformat=simple, labelsep=space, skip=10pt, labelfont=bf}
    531 \captionsetup[table]{labelformat=simple, labelsep=space, skip=10pt, labelfont=bf}
    532 \renewcommand{\thefigure}{\arabic{figure}}
    533 
    534 \renewcommand{\thetable}{\arabic{table}}
     528\captionsetup[figure]{labelformat=simple, labelsep=none, skip=10pt, labelfont=bf}
     529\captionsetup[table]{labelformat=simple, labelsep=none, skip=10pt, labelfont=bf}
     530\renewcommand{\thefigure}{\arabic{figure}\enspace }
     531
     532\renewcommand{\thetable}{\arabic{table}\enspace }
    535533
    536534\renewcommand\figurename{\textbf{FIGURE}}%%
     
    14141412\gdef\@stix@font@defn{%
    14151413  %
    1416 %  \def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}%
     1414  \def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}%
    14171415  %
    1418 %  \def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont}
     1416  \def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont}
    14191417  %
    14201418  \def\pagenumfont{\rmfamily\fontsize{7}{9}\bfseries\selectfont}%
     
    14291427  \def\arttypefont{\rmfamily\fontsize{9}{9}\fontseries{b}\selectfont}%
    14301428  \def\SParttypefont{\rmfamily\fontsize{9}{12}\fontseries{b}\selectfont}%
    1431   \def\titlefont{\rmfamily\fontsize{18}{23}\bfseries\selectfont\leftskip\z@\rightskip\z@ plus1fil}%
     1429  \def\titlefont{\rmfamily\fontsize{18}{23}\bfseries\selectfont\leftskip\z@\rightskip\z@ plus1fil\let\mathbcal\titmathbcal}%
    14321430  \def\subtitlefont{\rmfamily\fontsize{16}{21}\bfseries\selectfont\leftskip\z@\rightskip\z@ plus1fil}%
    14331431  \def\Authorfont{\rmfamily\fontsize{12}{18}\selectfont\leftskip\z@\rightskip\z@ plus1fil}%
     
    14841482\gdef\@lato@font@defn{%
    14851483  %
    1486 %  \def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}%
     1484  \def\infoboxfont{\fontfamily{tim}\fontsize{8}{8}\selectfont}%
    14871485  %
    1488 %  \def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont}
     1486  \def\watermarkfont{\reset@font\fontfamily{\ffdefault}\fontsize{45}{45}\bfseries\selectfont}
    14891487  %
    14901488  \def\pagenumfont{\rmfamily\fontsize{7}{9}\bfseries\selectfont}%
     
    32493247    \fi
    32503248  \fi%
    3251   \renewcommand\thefigure{\@Alph\c@section\arabic{figure}}%
    3252   \renewcommand\thetable{\@Alph\c@section\arabic{table}}%
     3249  \renewcommand\thefigure{\@Alph\c@section\arabic{figure}\enspace }%
     3250  \renewcommand\thetable{\@Alph\c@section\arabic{table}\enspace }%
    32533251  \renewcommand\theequation{\@Alph\c@section\arabic{equation}}%
    32543252}{%
  • doc/papers/general/.gitignore

    r7d0a3ba r358cba0  
    88Paper.out.ps
    99WileyNJD-AMA.bst
     10evaluation.zip
  • doc/papers/general/Makefile

    r7d0a3ba r358cba0  
    4545        @rm -frv ${DOCUMENT} ${BASE}.ps WileyNJD-AMA.bst ${BASE}.out.ps ${Build}
    4646
     47Paper.zip :
     48        zip -x general/.gitignore -x general/"*AMA*" -x general/Paper.out.ps -x general/Paper.tex.plain -x general/evaluation.zip -x general/mail -x general/response -x general/test.c -x general/evaluation.zip -x general/Paper.tex.plain -x general/Paper.ps -x general/Paper.pdf -x general/"*build*" -x general/evaluation/.gitignore -x general/evaluation/timing.xlsx -r Paper.zip general
     49
     50evaluation.zip :
     51        zip -x evaluation/.gitignore  -x evaluation/timing.xlsx -x evaluation/timing.dat -r evaluation.zip evaluation
     52
    4753# File Dependencies #
    4854
     
    6672## Define the default recipes.
    6773
    68 ${Build}:
     74${Build} :
    6975        mkdir -p ${Build}
    7076
    71 ${BASE}.out.ps: ${Build}
     77${BASE}.out.ps : ${Build}
    7278        ln -fs ${Build}/Paper.out.ps .
    7379
    74 WileyNJD-AMA.bst:
     80WileyNJD-AMA.bst :
    7581        ln -fs ../AMA/AMA-stix/ama/WileyNJD-AMA.bst .
    7682
  • doc/papers/general/Paper.tex

    r7d0a3ba r358cba0  
    5959%\DeclareTextCommandDefault{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}
    6060\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
     61
     62\renewcommand*{\thefootnote}{\Alph{footnote}} % hack because fnsymbol does not work
     63%\renewcommand*{\thefootnote}{\fnsymbol{footnote}}
    6164
    6265\makeatletter
     
    174177\lstMakeShortInline@%
    175178
     179\let\OLDthebibliography\thebibliography
     180\renewcommand\thebibliography[1]{
     181  \OLDthebibliography{#1}
     182  \setlength{\parskip}{0pt}
     183  \setlength{\itemsep}{4pt plus 0.3ex}
     184}
    176185
    177186\title{\texorpdfstring{\protect\CFA : Adding Modern Programming Language Features to C}{Cforall : Adding Modern Programming Language Features to C}}
     
    191200The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems to hobby projects.
    192201This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    193 Nevertheless, C, first standardized over thirty years ago, lacks many features that make programming in more modern languages safer and more productive.
    194 The goal of the \CFA project is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers.
     202Nevertheless, C, first standardized almost forty years ago, lacks many features that make programming in more modern languages safer and more productive.
     203
     204The goal of the \CFA project (pronounced ``C-for-all'') is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers.
    195205Prior projects have attempted similar goals but failed to honour C programming-style; for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers.
    196206Specifically, \CFA is designed to have an orthogonal feature-set based closely on the C programming paradigm, so that \CFA features can be added \emph{incrementally} to existing C code-bases, and C programmers can learn \CFA extensions on an as-needed basis, preserving investment in existing code and programmers.
     
    226236Love it or hate it, C is extremely popular, highly used, and one of the few systems languages.
    227237In many cases, \CC is often used solely as a better C.
    228 Nevertheless, C, first standardized over thirty years ago, lacks many features that make programming in more modern languages safer and more productive.
     238Nevertheless, C, first standardized almost forty years ago~\cite{ANSI89:C}, lacks many features that make programming in more modern languages safer and more productive.
    229239
    230240\CFA (pronounced ``C-for-all'', and written \CFA or Cforall) is an evolutionary extension of the C programming language that adds modern language-features to C, while maintaining both source and runtime compatibility with C and a familiar programming model for programmers.
     
    239249All languages features discussed in this paper are working, except some advanced exception-handling features.
    240250Not discussed in this paper are the integrated concurrency-constructs and user-level threading-library~\cite{Delisle18}.
    241 \CFA is an \emph{open-source} project implemented as an source-to-source translator from \CFA to the gcc-dialect of C~\cite{GCCExtensions}, allowing it to leverage the portability and code optimizations provided by gcc, meeting goals (1)--(3).
     251\CFA is an \emph{open-source} project implemented as a source-to-source translator from \CFA to the gcc-dialect of C~\cite{GCCExtensions}, allowing it to leverage the portability and code optimizations provided by gcc, meeting goals (1)--(3).
    242252Ultimately, a compiler is necessary for advanced features and optimal performance.
    243253% @plg2[9]% cd cfa-cc/src; cloc ArgTweak CodeGen CodeTools Common Concurrency ControlStruct Designators GenPoly InitTweak MakeLibCfa.cc MakeLibCfa.h Parser ResolvExpr SymTab SynTree Tuples driver prelude main.cc
     
    292302The \CFA tests are 290+ files and 27,000+ lines of code.
    293303The tests illustrate syntactic and semantic features in \CFA, plus a growing number of runtime benchmarks.
    294 The tests check for correctness and are used for daily regression testing of commits (3800+).
     304The tests check for correctness and are used for daily regression testing of 3800+ commits.
    295305
    296306Finally, it is impossible to describe a programming language without usages before definitions.
     
    313323There are only two hard things in Computer Science: cache invalidation and \emph{naming things} -- Phil Karlton
    314324\end{quote}
    315 \vspace{-10pt}
     325\vspace{-9pt}
    316326C already has a limited form of ad-hoc polymorphism in the form of its basic arithmetic operators, which apply to a variety of different types using identical syntax.
    317327\CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable;
     
    324334int max( int a, int b ) { return a < b ? b : a; }  $\C{// (3)}$
    325335double max( double a, double b ) { return a < b ? b : a; }  $\C{// (4)}\CRT$
    326 max( 7, -max );                                         $\C[2.75in]{// uses (3) and (1), by matching int from constant 7}$
     336max( 7, -max );                                         $\C{// uses (3) and (1), by matching int from constant 7}$
    327337max( max, 3.14 );                                       $\C{// uses (4) and (2), by matching double from constant 3.14}$
    328 max( max, -max );                                       $\C{// ERROR: ambiguous}$
    329 int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}\CRT$
     338max( max, -max );                                       $\C{// ERROR, ambiguous}$
     339int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}$
    330340\end{cfa}
    331341
     
    336346As is shown later, there are a number of situations where \CFA takes advantage of available type information to disambiguate, where other programming languages generate ambiguities.
    337347
    338 \Celeven added @_Generic@ expressions, which is used in preprocessor macros to provide a form of ad-hoc polymorphism;
     348\Celeven added @_Generic@ expressions~\cite[\S~6.5.1.1]{C11}, which is used with preprocessor macros to provide ad-hoc polymorphism;
    339349however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading.
    340350The macro wrapping the generic expression imposes some limitations;
    341351\eg, it cannot implement the example above, because the variables @max@ are ambiguous with the functions @max@.
    342352Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the dispatch functions, which must all have distinct names.
    343 For backwards compatibility, \CFA supports @_Generic@ expressions, but it is an unnecessary mechanism. \TODO{actually implement that}
     353\CFA supports @_Generic@ expressions for backwards compatibility, but it is an unnecessary mechanism. \TODO{actually implement that}
    344354
    345355% http://fanf.livejournal.com/144696.html
     
    369379\begin{cfa}
    370380forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x `+` x; }  $\C{// ? denotes operands}$
    371 int val = twice( twice( 3.7 ) );
     381int val = twice( twice( 3.7 ) );  $\C{// val == 14}$
    372382\end{cfa}
    373383which works for any type @T@ with a matching addition operator.
    374384The polymorphism is achieved by creating a wrapper function for calling @+@ with @T@ bound to @double@, then passing this function to the first call of @twice@.
    375385There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} in its type analysis.
    376 The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an eager conversion to @int@.
     386The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an early conversion to @int@.
    377387\CFA minimizes the number of conversions and their potential to lose information, so it selects the first approach, which corresponds with C-programmer intuition.
    378388
     
    420430\begin{cfa}
    421431forall( otype T | { int ?<?( T, T ); } ) void qsort( const T * arr, size_t size ) { /* use C qsort */ }
    422 {
     432int main() {
    423433        int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behaviour}$
    424         qsort( vals, size );                                    $\C{// descending sort}$
     434        qsort( vals, 10 );                                                      $\C{// descending sort}$
    425435}
    426436\end{cfa}
     
    428438Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types.
    429439
    430 To reducing duplication, it is possible to distribute a group of @forall@ (and storage-class qualifiers) over functions/types, so each block declaration is prefixed by the group (see example in Appendix~\ref{s:CforallStack}).
     440To reduce duplication, it is possible to distribute a group of @forall@ (and storage-class qualifiers) over functions/types, so each block declaration is prefixed by the group (see example in Appendix~\ref{s:CforallStack}).
    431441\begin{cfa}
    432442forall( otype `T` ) {                                                   $\C{// distribution block, add forall qualifier to declarations}$
     
    470480\end{cquote}
    471481
    472 In fact, the set of @summable@ trait operators is incomplete, as it is missing assignment for type @T@, but @otype@ is syntactic sugar for the following implicit trait:
     482Note, the @sumable@ trait does not include a copy constructor needed for the right side of @?+=?@ and return;
     483it is provided by @otype@, which is syntactic sugar for the following trait:
    473484\begin{cfa}
    474485trait otype( dtype T | sized(T) ) {  // sized is a pseudo-trait for types with known size and alignment
     
    488499Instead, each polymorphic function (or generic type) defines the structural type needed for its execution (polymorphic type-key), and this key is fulfilled at each call site from the lexical environment, which is similar to Go~\cite{Go} interfaces.
    489500Hence, new lexical scopes and nested functions are used extensively to create local subtypes, as in the @qsort@ example, without having to manage a nominal-inheritance hierarchy.
    490 (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.)
     501% (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.)
    491502
    492503% Nominal inheritance can be simulated with traits using marker variables or functions:
     
    515526
    516527
    517 \vspace*{-2pt}
    518528\section{Generic Types}
    519529
     
    534544\begin{cquote}
    535545\lstDeleteShortInline@%
    536 \begin{tabular}{@{}l|@{\hspace{2\parindentlnth}}l@{}}
    537 \begin{cfa}
    538 forall( otype R, otype S ) struct pair {
     546\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     547\begin{cfa}
     548`forall( otype R, otype S )` struct pair {
    539549        R first;        S second;
    540550};
     
    561571Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters.
    562572A \newterm{dtype-static} type has polymorphic parameters but is still concrete.
    563 Polymorphic pointers are an example of dtype-static types, \eg @forall(dtype T) T *@ is a polymorphic type, but for any @T@, @T *@  is a fixed-sized pointer, and therefore, can be represented by a @void *@ in code generation.
     573Polymorphic pointers are an example of dtype-static types;
     574given some type variable @T@, @T@ is a polymorphic type, as is @T *@, but @T *@ has a fixed size and can therefore be represented by @void *@ in code generation.
    564575
    565576\CFA generic types also allow checked argument-constraints.
     
    578589\begin{cfa}
    579590struct _pair_conc0 {
    580         const char * first;
    581         int second;
     591        const char * first;  int second;
    582592};
    583593\end{cfa}
     
    587597\begin{cfa}
    588598struct _pair_conc1 {
    589         void * first;
    590         void * second;
     599        void * first, * second;
    591600};
    592601\end{cfa}
     
    645654\begin{cquote}
    646655\lstDeleteShortInline@%
    647 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
     656\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
    648657\begin{cfa}
    649658forall( dtype Unit ) struct scalar { unsigned long value; };
     
    661670                                                        half_marathon;
    662671scalar(litres) two_pools = pool + pool;
    663 `marathon + pool;`      // compilation ERROR
     672`marathon + pool;`      // ERROR, mismatched types
    664673\end{cfa}
    665674\end{tabular}
     
    947956}
    948957\end{cfa}
    949 One more step permits the summation of any summable type with all arguments of the same type:
    950 \begin{cfa}
    951 trait summable( otype T ) {
     958One more step permits the summation of any sumable type with all arguments of the same type:
     959\begin{cfa}
     960trait sumable( otype T ) {
    952961        T ?+?( T, T );
    953962};
    954 forall( otype R | summable( R ) ) R sum( R x, R y ) {
     963forall( otype R | sumable( R ) ) R sum( R x, R y ) {
    955964        return x + y;
    956965}
    957 forall( otype R, ttype Params | summable(R) | { R sum(R, Params); } ) R sum(R x, R y, Params rest) {
     966forall( otype R, ttype Params | sumable(R) | { R sum(R, Params); } ) R sum(R x, R y, Params rest) {
    958967        return sum( x + y, rest );
    959968}
     
    10061015\begin{cfa}
    10071016forall( dtype T0, dtype T1 | sized(T0) | sized(T1) ) struct _tuple2 {
    1008         T0 field_0;                                                             $\C{// generated before the first 2-tuple}$
    1009         T1 field_1;
     1017        T0 field_0;  T1 field_1;                                        $\C{// generated before the first 2-tuple}$
    10101018};
    10111019_tuple2(int, int) f() {
    10121020        _tuple2(double, double) x;
    10131021        forall( dtype T0, dtype T1, dtype T2 | sized(T0) | sized(T1) | sized(T2) ) struct _tuple3 {
    1014                 T0 field_0;                                                     $\C{// generated before the first 3-tuple}$
    1015                 T1 field_1;
    1016                 T2 field_2;
     1022                T0 field_0;  T1 field_1;  T2 field_2;   $\C{// generated before the first 3-tuple}$
    10171023        };
    10181024        _tuple3(int, double, int) y;
    10191025}
    10201026\end{cfa}
    1021 {\sloppy
    1022 Tuple expressions are then simply converted directly into compound literals, \eg @[5, 'x', 1.24]@ becomes @(_tuple3(int, char, double)){ 5, 'x', 1.24 }@.
    1023 \par}%
     1027Tuple expressions are then converted directly into compound literals, \eg @[5, 'x', 1.24]@ becomes @(_tuple3(int, char,@ @double)){ 5, 'x', 1.24 }@.
    10241028
    10251029\begin{comment}
     
    11061110\lstDeleteShortInline@%
    11071111\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1108 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1112\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    11091113\begin{cfa}
    11101114case 2, 10, 34, 42:
     
    11211125\lstDeleteShortInline@%
    11221126\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1123 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1127\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    11241128\begin{cfa}
    11251129case 2~42:
     
    11741178\centering
    11751179\lstDeleteShortInline@%
    1176 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1177 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1180\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     1181\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    11781182\begin{cfa}
    11791183`choose` ( day ) {
    11801184  case Mon~Thu:  // program
    11811185
    1182   case Fri:  // program
     1186  case Fri:    // program
    11831187        wallet += pay;
    11841188        `fallthrough;`
    1185   case Sat:  // party
     1189  case Sat:   // party
    11861190        wallet -= party;
    11871191
    11881192  case Sun:  // rest
    11891193
    1190   default:  // error
     1194  default:    // print error
    11911195}
    11921196\end{cfa}
     
    11961200  case Mon: case Tue: case Wed: case Thu:  // program
    11971201        `break;`
    1198   case Fri:  // program
     1202  case Fri:    // program
    11991203        wallet += pay;
    12001204
    1201   case Sat:  // party
     1205  case Sat:   // party
    12021206        wallet -= party;
    12031207        `break;`
    12041208  case Sun:  // rest
    12051209        `break;`
    1206   default:  // error
     1210  default:    // print error
    12071211}
    12081212\end{cfa}
     
    12201224\centering
    12211225\lstDeleteShortInline@%
    1222 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1223 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{non-terminator}}  & \multicolumn{1}{c}{\textbf{target label}}     \\
     1226\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     1227\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{non-terminator}}       & \multicolumn{1}{c@{}}{\textbf{target label}}  \\
    12241228\begin{cfa}
    12251229choose ( ... ) {
     
    12641268\begin{figure}
    12651269\lstDeleteShortInline@%
    1266 \begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
    1267 \multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}   & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
     1270\begin{tabular}{@{\hspace{\parindentlnth}}l|@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     1271\multicolumn{1}{@{\hspace{\parindentlnth}}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}}  & \multicolumn{1}{@{\hspace{\parindentlnth}}c@{}}{\textbf{C}}   \\
    12681272\begin{cfa}
    12691273`LC:` {
     
    13491353\subsection{Exception Handling}
    13501354
    1351 The following framework for \CFA exception handling is in place, excluding some runtime type-information and virtual functions.
     1355The following framework for \CFA exception-handling is in place, excluding some runtime type-information and virtual functions.
    13521356\CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling})~\cite{Buhr92b,Buhr00a}.
    13531357Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler.
     
    13601364\begin{cquote}
    13611365\lstDeleteShortInline@%
    1362 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1363 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}}      & \multicolumn{1}{c}{\textbf{Termination}}      \\
     1366\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     1367\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{Resumption}}   & \multicolumn{1}{c@{}}{\textbf{Termination}}   \\
    13641368\begin{cfa}
    13651369`exception R { int fix; };`
     
    14771481If an exception is raised and caught, the handler is run before the finally clause.
    14781482Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.
    1479 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses.
     1483Mimicking the @finally@ clause with mechanisms like RAII is non-trivial when there are multiple types and local accesses.
    14801484
    14811485
     
    15301534with ( s, t ) {
    15311535        j + k;                                                                  $\C{// unambiguous, s.j + t.k}$
    1532         m = 5.0;                                                                $\C{// unambiguous, t.m = 5.0}$
    1533         m = 1;                                                                  $\C{// unambiguous, s.m = 1}$
    1534         int a = m;                                                              $\C{// unambiguous, a = s.i }$
    1535         double b = m;                                                   $\C{// unambiguous, b = t.m}$
     1536        m = 5.0;                                                                $\C{// unambiguous, s.m = 5.0}$
     1537        m = 1;                                                                  $\C{// unambiguous, t.m = 1}$
     1538        int a = m;                                                              $\C{// unambiguous, a = t.m }$
     1539        double b = m;                                                   $\C{// unambiguous, b = s.m}$
    15361540        int c = s.i + t.i;                                              $\C{// unambiguous, qualification}$
    1537         (double)m;                                                              $\C{// unambiguous, cast}$
     1541        (double)m;                                                              $\C{// unambiguous, cast s.m}$
    15381542}
    15391543\end{cfa}
     
    15591563and implicitly opened \emph{after} a function-body open, to give them higher priority:
    15601564\begin{cfa}
    1561 void ?{}( S & s, int `i` ) with ( s ) `with( $\emph{\color{red}params}$ )` {
     1565void ?{}( S & s, int `i` ) with ( s ) `{` `with( $\emph{\color{red}params}$ )` {
    15621566        s.i = `i`; j = 3; m = 5.5;
    1563 }
     1567} `}`
    15641568\end{cfa}
    15651569Finally, a cast may be used to disambiguate among overload variables in a @with@ expression:
     
    16291633\lstDeleteShortInline@%
    16301634\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    1631 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1635\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    16321636\begin{cfa}
    16331637`[5] *` int x1;
     
    16571661\lstDeleteShortInline@%
    16581662\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1659 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1663\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    16601664\begin{cfa}
    16611665`*` int x, y;
    1662 int y;
    1663 \end{cfa}
    1664 &
    1665 \begin{cfa}
    1666 int `*`x, `*`y;
     1666int z;
     1667\end{cfa}
     1668&
     1669\begin{cfa}
     1670int `*`x, `*`y, z;
    16671671
    16681672\end{cfa}
     
    16701674\lstMakeShortInline@%
    16711675\end{cquote}
    1672 The downside of the \CFA semantics is the need to separate regular and pointer declarations.
     1676% The downside of the \CFA semantics is the need to separate regular and pointer declarations.
     1677The separation of regular and pointer declarations by \CFA declarations enforces greater clarity with only slightly more syntax.
    16731678
    16741679\begin{comment}
     
    16771682\lstDeleteShortInline@%
    16781683\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    1679 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
     1684\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
    16801685\begin{cfa}
    16811686[ 5 ] int z;
     
    17191724\lstDeleteShortInline@%
    17201725\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    1721 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
     1726\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
    17221727\begin{cfa}
    17231728extern const * const int x;
     
    17441749\lstDeleteShortInline@%
    17451750\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1746 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1751\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    17471752\begin{cfa}
    17481753y = (* int)x;
     
    17721777\lstDeleteShortInline@%
    17731778\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1774 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1779\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    17751780\begin{cfa}
    17761781[double] foo(), foo( int ), foo( double ) {...}
     
    17901795* [ * int ] ( int y ) gp;               $\C{// pointer to function returning pointer to int with int parameter}$
    17911796* [ ] ( int, char ) hp;                 $\C{// pointer to function returning no result with int and char parameters}$
    1792 * [ * int, int ] ( int ) jp;    $\C{// pointer to function returning pointer to int and int with int parameter}$
    1793 \end{cfa}
    1794 Note, a function name cannot be specified:
    1795 \begin{cfa}
    1796 * [ int x ] f () fp;                    $\C{// function name "f" is disallowed}\CRT$
    1797 \end{cfa}
     1797* [ * int, int ] ( int ) jp;    $\C{// pointer to function returning pointer to int and int with int parameter}\CRT$
     1798\end{cfa}
     1799Note, the name of the function pointer is specified last, as for other variable declarations.
    17981800
    17991801Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
     
    18521854This provides a much more orthogonal design for library implementors, obviating the need for workarounds such as @std::reference_wrapper@.
    18531855Secondly, \CFA references are rebindable, whereas \CC references have a fixed address.
    1854 \newsavebox{\LstBox}
    1855 \begin{lrbox}{\LstBox}
    1856 \lstset{basicstyle=\footnotesize\linespread{0.9}\sf}
    1857 \begin{cfa}
    1858 int & r = *new( int );
    1859 ...                                                                                     $\C{// non-null reference}$
    1860 delete &r;                                                                      $\C{// unmanaged (programmer) memory-management}$
    1861 r += 1;                                                                         $\C{// undefined reference}$
    1862 \end{cfa}
    1863 \end{lrbox}
    18641856Rebinding allows \CFA references to be default-initialized (\eg to a null pointer\footnote{
    1865 While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any non-managed languages (C/\CC), given that it only handles one of many different error situations:
    1866 \begin{cquote}
    1867 \usebox{\LstBox}
    1868 \end{cquote}
    1869 }%
    1870 ) and point to different addresses throughout their lifetime, like pointers.
     1857While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any non-managed languages (C/\CC), given that it only handles one of many different error situations, \eg using a pointer after its storage is deleted.}) and point to different addresses throughout their lifetime, like pointers.
    18711858Rebinding is accomplished by extending the existing syntax and semantics of the address-of operator in C.
    18721859
     
    18801867\begin{itemize}
    18811868\item
    1882 if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) than @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols).
     1869if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) then @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols).
    18831870       
    18841871\item
     
    19141901\end{cfa}
    19151902This allows complex values to be succinctly and efficiently passed to functions, without the syntactic overhead of explicit definition of a temporary variable or the runtime cost of pass-by-value.
    1916 \CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const hell} problem, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.
     1903\CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const poisoning} problem~\cite{Taylor10}, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.
    19171904
    19181905
     
    19281915\begin{tabular}{@{}l@{\hspace{3em}}l|l@{}}
    19291916\multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}}      & \multicolumn{1}{c|}{\textbf{C Implicit Hoisting}}     & \multicolumn{1}{c}{\textbf{\CFA}}     \\
    1930 \hline
    19311917\begin{cfa}
    19321918struct S {
     
    20081994The symbol \lstinline+^+ is used for the destructor name because it was the last binary operator that could be used in a unary context.}.
    20091995The name @{}@ comes from the syntax for the initializer: @struct S { int i, j; } s = `{` 2, 3 `}`@.
    2010 Like other \CFA operators, these names represent the syntax used to call the constructor or destructor, \eg @?{}(x, ...)@ or @^{}(x, ...)@.
     1996Like other \CFA operators, these names represent the syntax used to explicitly call the constructor or destructor, \eg @s{...}@ or @^s{...}@.
    20111997The constructor and destructor have return type @void@, and the first parameter is a reference to the object type to be constructed or destructed.
    20121998While the first parameter is informally called the @this@ parameter, as in object-oriented languages, any variable name may be used.
    2013 Both constructors and destructors allow additional parametes after the @this@ parameter for specifying values for initialization/de-initialization\footnote{
     1999Both constructors and destructors allow additional parameters after the @this@ parameter for specifying values for initialization/de-initialization\footnote{
    20142000Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}.
    20152001\begin{cfa}
     
    20182004void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$
    20192005{
    2020         VLA x;                                                                  $\C{// implicit:  ?\{\}( x );}$
    2021 }                                                                                       $\C{// implicit:  ?\^{}\{\}( x );}$
     2006        VLA x;                                                                  $\C{// implicit:\ \ x\{\};}$
     2007}                                                                                       $\C{// implicit:\ \textasciicircum{}x\{\};}$
    20222008\end{cfa}
    20232009@VLA@ is a \newterm{managed type}\footnote{
     
    20442030appropriate care is taken to not recursively call the copy constructor when initializing the second parameter.
    20452031
    2046 \CFA constructors may be explicitly call, like Java, and destructors may be explicitly called, like \CC.
     2032\CFA constructors may be explicitly called, like Java, and destructors may be explicitly called, like \CC.
    20472033Explicit calls to constructors double as a \CC-style \emph{placement syntax}, useful for construction of member fields in user-defined constructors and reuse of existing storage allocations.
    2048 While existing call syntax works for explicit calls to constructors and destructors, \CFA also provides a more concise \newterm{operator syntax} for both:
     2034Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls:
    20492035\begin{cfa}
    20502036{
    20512037        VLA  x,            y = { 20, 0x01 },     z = y; $\C{// z points to y}$
    2052         //      ?{}( x );   ?{}( y, 20, 0x01 );   ?{}( z, y );
     2038        //    x{};         y{ 20, 0x01 };          z{ z, y };
    20532039        ^x{};                                                                   $\C{// deallocate x}$
    20542040        x{};                                                                    $\C{// reallocate x}$
     
    20572043        y{ x };                                                                 $\C{// reallocate y, points to x}$
    20582044        x{};                                                                    $\C{// reallocate x, not pointing to y}$
    2059         // ^?{}(z);  ^?{}(y);  ^?{}(x);
     2045        //  ^z{};  ^y{};  ^x{};
    20602046}
    20612047\end{cfa}
     
    20782064In these cases, \CFA provides the initialization syntax \lstinline|S x `@=` {}|, and the object becomes unmanaged, so implicit constructor and destructor calls are not generated.
    20792065Any C initializer can be the right-hand side of an \lstinline|@=| initializer, \eg \lstinline|VLA a @= { 0, 0x0 }|, with the usual C initialization semantics.
    2080 The same syntax can be used in a compound literal, \eg \lstinline|a = VLA`@`{ 0, 0x0 }|, to create a C-style literal.
     2066The same syntax can be used in a compound literal, \eg \lstinline|a = (VLA)`@`{ 0, 0x0 }|, to create a C-style literal.
    20812067The point of \lstinline|@=| is to provide a migration path from legacy C code to \CFA, by providing a mechanism to incrementally convert to implicit initialization.
    20822068
     
    21342120
    21352121In C, @0@ has the special property that it is the only ``false'' value;
    2136 from the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true.
     2122by the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true.
    21372123As such, an expression @x@ in any boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to @&&@, @||@, or @?:@\,) can be rewritten as @x != 0@ without changing its semantics.
    21382124Operator overloading in \CFA provides a natural means to implement this truth-value comparison for arbitrary types, but the C type system is not precise enough to distinguish an equality comparison with @0@ from an equality comparison with an arbitrary integer or pointer.
     
    21692155\lstDeleteShortInline@%
    21702156\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    2171 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{postfix function}}        & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{constant}}      & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{variable/expression}}   & \multicolumn{1}{c}{\textbf{postfix pointer}}  \\
     2157\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{postfix function}}     & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{constant}}      & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{variable/expression}}   & \multicolumn{1}{c@{}}{\textbf{postfix pointer}}       \\
    21722158\begin{cfa}
    21732159int |?`h|( int s );
     
    22142200\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    22152201\lstDeleteShortInline@%
    2216 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2217 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{\CC}}      \\
     2202\begin{tabular}{@{}l@{\hspace{1.25\parindentlnth}}l@{}}
     2203\multicolumn{1}{@{}c@{\hspace{1.25\parindentlnth}}}{\textbf{\CFA}}      & \multicolumn{1}{c@{}}{\textbf{\CC}}   \\
    22182204\begin{cfa}
    22192205struct W {
     
    22592245        W w, heavy = { 20 };
    22602246        w = 155|_lb|;
    2261         w = 0b1111|_lb|;       // error, binary unsupported
     2247        // binary unsupported
    22622248        w = 0${\color{red}\LstBasicStyle{'}}$233|_lb|;          // quote separator
    22632249        w = 0x9b|_kg|;
     
    22892275\lstDeleteShortInline@%
    22902276\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2291 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}      & \multicolumn{1}{c}{\textbf{Usage}}    \\
     2277\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}   & \multicolumn{1}{c@{}}{\textbf{Usage}} \\
    22922278\begin{cfa}
    22932279const short int `MIN` = -32768;
     
    23072293\begin{cquote}
    23082294\lstDeleteShortInline@%
    2309 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2310 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     2295\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     2296\multicolumn{1}{@{}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}  & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    23112297\begin{cfa}
    23122298MIN
    2313 
    23142299MAX
    2315 
    23162300PI
    23172301E
     
    23192303&
    23202304\begin{cfa}
    2321 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN,
    2322         LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN
    2323 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX,
    2324         LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX
     2305CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN
     2306UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX
    23252307M_PI, M_PIl
    23262308M_E, M_El
     
    23382320\lstDeleteShortInline@%
    23392321\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2340 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}      & \multicolumn{1}{c}{\textbf{Usage}}    \\
     2322\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}   & \multicolumn{1}{c@{}}{\textbf{Usage}} \\
    23412323\begin{cfa}
    23422324float `log`( float x );
     
    23572339\lstDeleteShortInline@%
    23582340\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2359 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     2341\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    23602342\begin{cfa}
    23612343log
     
    23852367\lstDeleteShortInline@%
    23862368\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2387 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}      & \multicolumn{1}{c}{\textbf{Usage}}    \\
     2369\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}   & \multicolumn{1}{c@{}}{\textbf{Usage}} \\
    23882370\begin{cfa}
    23892371unsigned int `abs`( int );
     
    24042386\lstDeleteShortInline@%
    24052387\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2406 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     2388\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    24072389\begin{cfa}
    24082390abs
     
    24272409an allocation with a specified character.
    24282410\item[resize]
    2429 an existing allocation to decreased or increased its size.
     2411an existing allocation to decrease or increase its size.
    24302412In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied.
    24312413For an increase in storage size, new storage after the copied data may be filled.
     
    24412423
    24422424\begin{table}
     2425\caption{Storage-Management Operations}
     2426\label{t:StorageManagementOperations}
    24432427\centering
    24442428\lstDeleteShortInline@%
     
    24602444\lstDeleteShortInline~%
    24612445\lstMakeShortInline@%
    2462 \caption{Storage-Management Operations}
    2463 \label{t:StorageManagementOperations}
    24642446\end{table}
    24652447
    24662448\begin{figure}
    24672449\centering
    2468 \begin{cquote}
    2469 \begin{cfa}[aboveskip=0pt]
     2450\begin{cfa}[aboveskip=0pt,xleftmargin=0pt]
    24702451size_t  dim = 10;                                                       $\C{// array dimension}$
    24712452char fill = '\xff';                                                     $\C{// initialization fill value}$
     
    24732454\end{cfa}
    24742455\lstDeleteShortInline@%
    2475 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2476 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
    2477 \begin{cfa}
     2456\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     2457\multicolumn{1}{@{}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}  & \multicolumn{1}{c@{}}{\textbf{C}}     \\
     2458\begin{cfa}[xleftmargin=-10pt]
    24782459ip = alloc();
    24792460ip = alloc( fill );
     
    24902471&
    24912472\begin{cfa}
    2492 ip = (int *)malloc( sizeof( int ) );
    2493 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2494 ip = (int *)malloc( dim * sizeof( int ) );
    2495 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2496 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) );
    2497 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) );
    2498                         memset( ip, fill, 4 * dim * sizeof( int ) );
    2499 ip = memalign( 16, sizeof( int ) );
    2500 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2501 ip = memalign( 16, dim * sizeof( int ) );
    2502 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2503 \end{cfa}
    2504 \end{tabular}
    2505 \lstMakeShortInline@%
    2506 \end{cquote}
     2473ip = (int *)malloc( sizeof(int) );
     2474ip = (int *)malloc( sizeof(int) ); memset( ip, fill, sizeof(int) );
     2475ip = (int *)malloc( dim * sizeof(int) );
     2476ip = (int *)malloc( sizeof(int) ); memset( ip, fill, dim * sizeof(int) );
     2477ip = (int *)realloc( ip, 2 * dim * sizeof(int) );
     2478ip = (int *)realloc( ip, 4 * dim * sizeof(int) ); memset( ip, fill, 4 * dim * sizeof(int));
     2479
     2480ip = memalign( 16, sizeof(int) );
     2481ip = memalign( 16, sizeof(int) ); memset( ip, fill, sizeof(int) );
     2482ip = memalign( 16, dim * sizeof(int) );
     2483ip = memalign( 16, dim * sizeof(int) ); memset( ip, fill, dim * sizeof(int) );
     2484\end{cfa}
     2485\end{tabular}
     2486\lstMakeShortInline@%
    25072487\caption{\CFA versus C Storage-Allocation}
    25082488\label{f:StorageAllocation}
     
    25172497S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
    25182498\end{cfa}
    2519 Note, \CC can only initialization array elements via the default constructor.
     2499Note, \CC can only initialize array elements via the default constructor.
    25202500
    25212501Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
     
    25342514\lstDeleteShortInline@%
    25352515\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2536 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{\CC}}      \\
     2516\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{\CC}}   \\
    25372517\begin{cfa}
    25382518int x = 1, y = 2, z = 3;
     
    25892569\end{cquote}
    25902570There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
    2591 
     2571\begin{comment}
    25922572The implicit separator character (space/blank) is a separator not a terminator.
    25932573The rules for implicitly adding the separator are:
     
    26082588}%
    26092589\end{itemize}
     2590\end{comment}
    26102591There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.
    26112592
     
    26222603\centering
    26232604\lstDeleteShortInline@%
    2624 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}@{\hspace{2\parindentlnth}}l@{}}
    2625 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{@{\hspace{2\parindentlnth}}c}{\textbf{C}}     \\
     2605\begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
     2606\multicolumn{1}{@{}c@{\hspace{3\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    26262607\begin{cfa}
    26272608#include <gmp>
     
    26562637
    26572638
    2658 \section{Evaluation}
     2639\section{Polymorphism Evaluation}
    26592640\label{sec:eval}
    26602641
    2661 Though \CFA provides significant added functionality over C, these features have a low runtime penalty.
    2662 In fact, \CFA's features for generic programming can enable faster runtime execution than idiomatic @void *@-based C code.
    2663 This claim is demonstrated through a set of generic-code-based micro-benchmarks in C, \CFA, and \CC (see stack implementations in Appendix~\ref{sec:BenchmarkStackImplementations}).
     2642\CFA adds parametric polymorphism to C.
     2643A runtime evaluation is performed to compare the cost of alternative styles of polymorphism.
     2644The goal is to compare just the underlying mechanism for implementing different kinds of polymorphism.
     2645% Though \CFA provides significant added functionality over C, these features have a low runtime penalty.
     2646% In fact, it is shown that \CFA's generic programming can enable faster runtime execution than idiomatic @void *@-based C code.
     2647The experiment is a set of generic-stack micro-benchmarks~\cite{CFAStackEvaluation} in C, \CFA, and \CC (see implementations in Appendix~\ref{sec:BenchmarkStackImplementations}).
    26642648Since all these languages share a subset essentially comprising standard C, maximal-performance benchmarks should show little runtime variance, differing only in length and clarity of source code.
    26652649A more illustrative comparison measures the costs of idiomatic usage of each language's features.
     
    26922676\end{figure}
    26932677
    2694 The structure of each benchmark implemented is: C with @void *@-based polymorphism, \CFA with the presented features, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV.
     2678The structure of each benchmark implemented is: C with @void *@-based polymorphism, \CFA with parametric polymorphism, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV.
    26952679The \CCV variant illustrates an alternative object-oriented idiom where all objects inherit from a base @object@ class, mimicking a Java-like interface;
    26962680hence runtime checks are necessary to safely down-cast objects.
    26972681The most notable difference among the implementations is in memory layout of generic types: \CFA and \CC inline the stack and pair elements into corresponding list and pair nodes, while C and \CCV lack such a capability and instead must store generic objects via pointers to separately-allocated objects.
    2698 Note that the C benchmark uses unchecked casts as there is no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically.
     2682Note, the C benchmark uses unchecked casts as C has no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically.
    26992683
    27002684Figure~\ref{fig:eval} and Table~\ref{tab:eval} show the results of running the benchmark in Figure~\ref{fig:BenchmarkTest} and its C, \CC, and \CCV equivalents.
     
    27112695
    27122696\begin{table}
    2713 \centering
    27142697\caption{Properties of benchmark code}
    27152698\label{tab:eval}
     2699\centering
    27162700\newcommand{\CT}[1]{\multicolumn{1}{c}{#1}}
    27172701\begin{tabular}{rrrrr}
     
    27262710The C and \CCV variants are generally the slowest with the largest memory footprint, because of their less-efficient memory layout and the pointer-indirection necessary to implement generic types;
    27272711this inefficiency is exacerbated by the second level of generic types in the pair benchmarks.
    2728 By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair of @short@ and @char@ because the storage layout is equivalent, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead.
     2712By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair because of equivalent storage layout, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead.
    27292713\CCV is slower than C largely due to the cost of runtime type-checking of down-casts (implemented with @dynamic_cast@);
    2730 The outlier in the graph for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code.
    2731 The gcc compiler is unable to optimize some dead code and condense nested calls; a compiler designed for \CFA could easily perform these optimizations.
     2714The outlier for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code.
     2715The gcc compiler is unable to optimize some dead code and condense nested calls;
     2716a compiler designed for \CFA could easily perform these optimizations.
    27322717Finally, the binary size for \CFA is larger because of static linking with the \CFA libraries.
    27332718
     
    27412726Line-count is a fairly rough measure of code complexity;
    27422727another important factor is how much type information the programmer must specify manually, especially where that information is not compiler-checked.
    2743 Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of untype-checked downcasts, \eg @object@ to @integer@ when popping a stack.
     2728Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of un-type-checked downcasts, \eg @object@ to @integer@ when popping a stack.
    27442729To quantify this manual typing, the ``redundant type annotations'' line in Table~\ref{tab:eval} counts the number of lines on which the type of a known variable is respecified, either as a format specifier, explicit downcast, type-specific function, or by name in a @sizeof@, struct literal, or @new@ expression.
    27452730The \CC benchmark uses two redundant type annotations to create a new stack nodes, while the C and \CCV benchmarks have several such annotations spread throughout their code.
    27462731The \CFA benchmark is able to eliminate all redundant type annotations through use of the polymorphic @alloc@ function discussed in Section~\ref{sec:libraries}.
    27472732
     2733We conjecture these results scale across most generic data-types as the underlying polymorphism implement is constant.
     2734
    27482735
    27492736\section{Related Work}
     
    27512738
    27522739\subsection{Polymorphism}
     2740
     2741ML~\cite{ML} was the first language to support parametric polymorphism.
     2742Like \CFA, it supports universal type parameters, but not the use of assertions and traits to constrain type arguments.
     2743Haskell~\cite{Haskell10} combines ML-style polymorphism, polymorphic data types, and type inference with the notion of type classes, collections of overloadable methods that correspond in intent to traits in \CFA.
     2744Unlike \CFA, Haskell requires an explicit association between types and their classes that specifies the implementation of operations.
     2745These associations determine the functions that are assertion arguments for particular combinations of class and type, in contrast to \CFA where the assertion arguments are selected at function call sites based upon the set of operations in scope at that point.
     2746Haskell also severely restricts the use of overloading: an overloaded name can only be associated with a single class, and methods with overloaded names can only be defined as part of instance declarations.
    27532747
    27542748\CC provides three disjoint polymorphic extensions to C: overloading, inheritance, and templates.
     
    28042798Go does not have tuples but supports MRVF.
    28052799Java's variadic functions appear similar to C's but are type-safe using homogeneous arrays, which are less useful than \CFA's heterogeneously-typed variadic functions.
    2806 Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML~\cite{sml} and~\cite{Scala}, which decompose tuples using pattern matching.
     2800Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML~\cite{sml}, Haskell, and Scala~\cite{Scala}, which decompose tuples using pattern matching.
    28072801
    28082802
     
    28352829Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable.
    28362830
    2837 There is ongoing work on a wide range of \CFA features, including arrays with size, runtime type-information, virtual functions, user-defined conversions, concurrent primitives, and modules.
    2838 While all examples in the paper compile and run, a public beta-release of \CFA will take another 8--12 months to finalize these extensions.
    2839 There are also interesting future directions for the polymorphism design.
    2840 Notably, \CC template functions trade compile time and code bloat for optimal runtime of individual instantiations of polymorphic functions.
    2841 \CFA polymorphic functions use dynamic virtual-dispatch;
    2842 the runtime overhead of this approach is low, but not as low as inlining, and it may be beneficial to provide a mechanism for performance-sensitive code.
     2831While all examples in the paper compile and run, a public beta-release of \CFA will take 6--8 months to reduce compilation time, provide better debugging, and add a few more libraries.
     2832There is also new work on a number of \CFA features, including arrays with size, runtime type-information, virtual functions, user-defined conversions, and modules.
     2833While \CFA polymorphic functions use dynamic virtual-dispatch with low runtime overhead (see Section~\ref{sec:eval}), it is not as low as \CC template-inlining.
     2834Hence it may be beneficial to provide a mechanism for performance-sensitive code.
    28432835Two promising approaches are an @inline@ annotation at polymorphic function call sites to create a template-specialization of the function (provided the code is visible) or placing an @inline@ annotation on polymorphic function-definitions to instantiate a specialized version for some set of types (\CC template specialization).
    28442836These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code-bloat.
     
    28492841
    28502842The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, Thierry Delisle, Andrew Beach and Brice Dobry on the features described in this paper, and thank Magnus Madsen for feedback on the writing.
    2851 This work is supported by a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada.
    2852 
    2853 
     2843Funding for this project has been provided by Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada.
     2844
     2845{%
     2846\fontsize{9bp}{12bp}\selectfont%
    28542847\bibliography{pl}
    2855 
     2848}%
    28562849
    28572850\appendix
  • doc/papers/general/evaluation/timing.gp

    r7d0a3ba r358cba0  
    2525
    2626set label "23.9" at 7.125,10.5
    27 
     27set style fill pattern 4 border lt -1
    2828# set datafile separator ","
    2929plot for [COL=2:5] 'evaluation/timing.dat' using (column(COL)/SCALE):xticlabels(1) title columnheader
  • src/CodeGen/CodeGenerator.cc

    r7d0a3ba r358cba0  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Sep  3 20:42:52 2017
    13 // Update Count     : 490
     12// Last Modified On : Sat May  5 09:08:32 2018
     13// Update Count     : 494
    1414//
    1515#include "CodeGenerator.h"
     
    370370
    371371        void CodeGenerator::postvisit( Constant * constant ) {
    372                 output << constant->get_value() ;
     372                output << constant->get_value();
    373373        }
    374374
     
    587587                output << "(";
    588588                if ( castExpr->get_result()->isVoid() ) {
    589                         output << "(void)" ;
     589                        output << "(void)";
    590590                } else {
    591591                        // at least one result type of cast.
     
    878878                        } // for
    879879                } // if
    880                 output << " );" ;
     880                output << " );";
    881881        }
    882882
     
    886886                output << "( ";
    887887                if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
    888                 output << " )" ;
     888                output << " )";
    889889        }
    890890
    891891        void CodeGenerator::postvisit( DirectiveStmt * dirStmt ) {
    892                 output << dirStmt->directive;
     892                output << endl << dirStmt->directive;                   // endl prevents spaces before directive
    893893        }
    894894
     
    907907
    908908        void CodeGenerator::postvisit( SwitchStmt * switchStmt ) {
    909                 output << "switch ( " ;
     909                output << "switch ( ";
    910910                switchStmt->get_condition()->accept( *visitor );
    911911                output << " ) ";
     
    933933                ++indent;
    934934                for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end();  i++) {
    935                         output << indent << printLabels( (*i)->get_labels() )  ;
     935                        output << indent << printLabels( (*i)->get_labels() ) ;
    936936                        (*i)->accept( *visitor );
    937937                        output << endl;
     
    10701070        void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
    10711071                if ( whileStmt->get_isDoWhile() ) {
    1072                         output << "do" ;
    1073                 } else {
    1074                         output << "while (" ;
     1072                        output << "do";
     1073                } else {
     1074                        output << "while (";
    10751075                        whileStmt->get_condition()->accept( *visitor );
    10761076                        output << ")";
     
    10841084
    10851085                if ( whileStmt->get_isDoWhile() ) {
    1086                         output << " while (" ;
     1086                        output << " while (";
    10871087                        whileStmt->get_condition()->accept( *visitor );
    10881088                        output << ");";
  • src/CodeGen/FixNames.cc

    r7d0a3ba r358cba0  
    5656                auto && name = SymTab::Mangler::mangle( mainDecl.get() );
    5757                // std::cerr << name << std::endl;
    58                 return name;
     58                return std::move(name);
    5959        }
    6060        std::string mangle_main_args() {
     
    7979                auto&& name = SymTab::Mangler::mangle( mainDecl.get() );
    8080                // std::cerr << name << std::endl;
    81                 return name;
     81                return std::move(name);
    8282        }
    8383
  • src/Common/Heap.cc

    r7d0a3ba r358cba0  
    77// Heap.cc --
    88//
    9 // Author           : Peter A. Buhr
    10 // Created On       :
     9// Author           : Thierry Delisle
     10// Created On       : Thu May  3 16:16:10 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May  3 16:16:10 2018
    13 // Update Count     : 2
     12// Last Modified On : Fri May  4 17:27:31 2018
     13// Update Count     : 28
    1414//
    1515
    16 namespace HeapStats{
    17   void newPass( const char * const name ) {}
    18   void printStats() {}
     16#include <cassert>
     17#include <cmath>
     18#include <cstddef>
     19#include <cstring>
     20#include <iomanip>
     21#include <iostream>
     22
     23//#define WITH_HEAP_STATISTICS
     24
     25namespace HeapStats {
     26#if !defined( WITH_HEAP_STATISTICS )
     27        void newPass( const char * const ) {}
     28
     29        void printStats() {}
     30#else
     31        struct StatBlock {
     32                const char * name = nullptr;
     33                size_t mallocs    = 0;
     34                size_t frees      = 0;
     35        };
     36
     37        StatBlock    passes[100] = {{ "Pre-Parse", 0, 0 }};
     38        const size_t passes_size = sizeof(passes) / sizeof(passes[0]);
     39        size_t       passes_cnt = 1;
     40
     41        void newPass( const char * const name ) {
     42                passes[passes_cnt].name    = name;
     43                passes[passes_cnt].mallocs = 0;
     44                passes[passes_cnt].frees   = 0;
     45                passes_cnt++;
     46
     47                assertf(passes_cnt < passes_size, "Too many passes for HeapStats, increase the size of the array in Heap.h");
     48        }
     49
     50        void print(size_t value, size_t total) {
     51                std::cerr << std::setw(12) << value;
     52                std::cerr << "(" << std::setw(3);
     53                std::cerr << (value == 0 ? 0 : value * 100 / total);
     54                std::cerr << "%) | ";
     55        }
     56
     57        void print(const StatBlock& stat, size_t nc, size_t total_mallocs, size_t total_frees) {
     58                std::cerr << std::setw(nc) << stat.name;
     59                std::cerr << " | ";
     60
     61                print(stat.mallocs, total_mallocs);
     62                print(stat.frees  , total_frees  );
     63                std::cerr << "\n";
     64        }
     65
     66        void print(char c, size_t nc) {
     67                for(size_t i = 0; i < nc; i++) {
     68                        std::cerr << c;
     69                }
     70                std::cerr << '\n';
     71        }
     72
     73        void printStats() {
     74                size_t nc = 0;
     75                size_t total_mallocs = 0;
     76                size_t total_frees   = 0;
     77                for(size_t i = 0; i < passes_cnt; i++) {
     78                        nc = std::max(nc, std::strlen(passes[i].name));
     79                        total_mallocs += passes[i].mallocs;
     80                        total_frees   += passes[i].frees;
     81                }
     82                size_t nct = nc + 44;
     83
     84                const char * const title = "Heap Usage Statistic";
     85                print('=', nct);
     86                for(size_t i = 0; i < (nct - std::strlen(title)) / 2; i++) std::cerr << ' ';
     87                std::cerr << title << std::endl;
     88                print('-', nct);
     89                std::cerr << std::setw(nc) << "Pass";
     90                std::cerr << " |       Malloc Count |         Free Count |" << std::endl;
     91
     92                print('-', nct);
     93                for(size_t i = 0; i < passes_cnt; i++) {
     94                        print(passes[i], nc, total_mallocs, total_frees);
     95                }
     96                print('-', nct);
     97                print({"Sum", total_mallocs, total_frees}, nc, total_mallocs, total_frees);
     98
     99        }
     100
     101#include <stdarg.h>
     102#include <stddef.h>
     103#include <stdio.h>
     104#include <string.h>
     105#include <unistd.h>
     106#include <signal.h>
     107        extern "C" {
     108#include <dlfcn.h>
     109#include <execinfo.h>
     110        }
     111
     112//=============================================================================================
     113// Interposing helpers
     114//=============================================================================================
     115
     116        typedef void (* generic_fptr_t)(void);
     117        generic_fptr_t interpose_symbol( const char * symbol, const char * version ) {
     118                const char * error;
     119
     120                static void * library;
     121                if ( ! library ) {
     122#if defined( RTLD_NEXT )
     123                        library = RTLD_NEXT;
     124#else
     125                        // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
     126                        library = dlopen( "libc.so.6", RTLD_LAZY );
     127                        error = dlerror();
     128                        if ( error ) {
     129                                std::cerr << "interpose_symbol : failed to open libc, " << error << std::endl;
     130                                abort();
     131                        }
     132#endif // RTLD_NEXT
     133                } // if
     134
     135                generic_fptr_t fptr;
     136
     137#if defined( _GNU_SOURCE )
     138                if ( version ) {
     139                        fptr = (generic_fptr_t)dlvsym( library, symbol, version );
     140                } else {
     141                        fptr = (generic_fptr_t)dlsym( library, symbol );
     142                }
     143#else
     144                fptr = (generic_fptr_t)dlsym( library, symbol );
     145#endif // _GNU_SOURCE
     146
     147                error = dlerror();
     148                if ( error ) {
     149                        std::cerr << "interpose_symbol : internal error, " << error << std::endl;
     150                        abort();
     151                }
     152
     153                return fptr;
     154        }
     155
     156        extern "C" {
     157                void * malloc( size_t size ) __attribute__((malloc));
     158                void * malloc( size_t size ) {
     159                        static auto __malloc = reinterpret_cast<void * (*)(size_t)>(interpose_symbol( "malloc", nullptr ));
     160                        if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++;
     161                        return __malloc( size );
     162                }
     163
     164                void free( void * ptr ) {
     165                        static auto __free = reinterpret_cast<void   (*)(void *)>(interpose_symbol( "free", nullptr ));
     166                        if( passes_cnt > 0 ) passes[passes_cnt - 1].frees++;
     167                        return __free( ptr );
     168                }
     169
     170                void * calloc( size_t nelem, size_t size ) {
     171                        static auto __calloc = reinterpret_cast<void * (*)(size_t, size_t)>(interpose_symbol( "calloc", nullptr ));
     172                        if( passes_cnt > 0 ) passes[passes_cnt - 1].mallocs++;
     173                        return __calloc( nelem, size );
     174                }
     175
     176                void * realloc( void * ptr, size_t size ) {
     177                        static auto __realloc = reinterpret_cast<void * (*)(void *, size_t)>(interpose_symbol( "realloc", nullptr ));
     178                        void * s = __realloc( ptr, size );
     179                        if ( s != ptr && passes_cnt > 0 ) {                     // did realloc get new storage ?
     180                                passes[passes_cnt - 1].mallocs++;
     181                                passes[passes_cnt - 1].frees++;
     182                        } // if
     183                        return s;
     184                }
     185        }
     186#endif
    19187}
    20 
  • src/Common/Heap.h

    r7d0a3ba r358cba0  
    77// Heap.h --
    88//
    9 // Author           : Peter A. Buhr
    10 // Created On       :
     9// Author           : Thierry Delisle
     10// Created On       : Thu May  3 16:16:10 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May  3 16:16:10 2018
    13 // Update Count     : 2
     12// Last Modified On : Fri May  4 14:34:08 2018
     13// Update Count     : 3
    1414//
    1515
     
    1717
    1818namespace HeapStats {
    19   void newPass( const char * const name );
    20   void printStats();
     19        void newPass( const char * const name );
     20        void printStats();
    2121}
  • src/Common/PassVisitor.proto.h

    r7d0a3ba r358cba0  
    4747
    4848        operator bool() { return m_ref ? *m_ref : true; }
    49         bool operator=( bool val ) { return *m_ref = val; }
     49        bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
    5050
    5151private:
     
    5353        friend class ChildrenGuard;
    5454
    55         bool * set( bool & val ) {
     55        bool * set( bool * val ) {
    5656                bool * prev = m_ref;
    57                 m_ref = &val;
     57                m_ref = val;
    5858                return prev;
    5959        }
     
    6767        ChildrenGuard( bool_ref * ref )
    6868                : m_val ( true )
    69                 , m_prev( ref ? ref->set( m_val ) : nullptr )
     69                , m_prev( ref ? ref->set( &m_val ) : nullptr )
    7070                , m_ref ( ref )
    7171        {}
     
    7373        ~ChildrenGuard() {
    7474                if( m_ref ) {
    75                         m_ref->set( *m_prev );
     75                        m_ref->set( m_prev );
    7676                }
    7777        }
  • src/Common/utility.h

    r7d0a3ba r358cba0  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May  3 12:18:31 2018
    13 // Update Count     : 39
     12// Last Modified On : Sun May  6 22:24:16 2018
     13// Update Count     : 40
    1414//
    1515
     
    442442template<typename T>
    443443inline
    444 #if __GNUC__ > 4
     444#if defined(__GNUC__) && __GNUC__ > 4
    445445constexpr
    446446#endif
  • src/Parser/parser.yy

    r7d0a3ba r358cba0  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu May  3 08:20:09 2018
    13 // Update Count     : 3225
     12// Last Modified On : Fri May 11 17:51:38 2018
     13// Update Count     : 3261
    1414//
    1515
     
    302302
    303303%type<decl> field_declaration field_declaration_list field_declarator field_declaring_list
    304 %type<en> field field_list field_name fraction_constants
     304%type<en> field field_list field_name fraction_constants_opt
    305305
    306306%type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
     
    499499        | type_name '.' no_attr_identifier                                      // CFA, nested type
    500500                { SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; }
     501//              { $$ = nullptr; }
    501502        | type_name '.' '[' push field_list pop ']'                     // CFA, nested type / tuple field selector
    502503                { SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; }
     504//              { $$ = nullptr; }
    503505        | GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
    504506                { SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; }
     
    533535        | postfix_expression '.' no_attr_identifier
    534536                { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
     537        | postfix_expression '.' INTEGERconstant                        // CFA, tuple index
     538                { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger( *$3 ) ) ); }
     539        | postfix_expression FLOATING_FRACTIONconstant          // CFA, tuple index
     540                { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
    535541        | postfix_expression '.' '[' push field_list pop ']' // CFA, tuple field selector
    536542                { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $5 ) ) ); }
    537         | postfix_expression FLOATING_FRACTIONconstant          // CFA, tuple index
    538                 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
    539543        | postfix_expression ARROW no_attr_identifier
    540544                {
    541545                        $$ = new ExpressionNode( build_pfieldSel( $1, *$3 == "0" || *$3 == "1" ? build_constantInteger( *$3 ) : build_varref( $3 ) ) );
    542546                }
    543         | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
    544                         { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); }
    545547        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    546548                { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
     549        | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
     550                { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); }
    547551        | postfix_expression ICR
    548552                { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); }
     
    597601
    598602field_name:
    599         INTEGERconstant fraction_constants
     603        INTEGERconstant fraction_constants_opt
    600604                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); }
    601         | FLOATINGconstant fraction_constants
     605        | FLOATINGconstant fraction_constants_opt
    602606                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
    603         | no_attr_identifier fraction_constants
     607        | no_attr_identifier fraction_constants_opt
    604608                {
    605609                        $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     
    607611        ;
    608612
    609 fraction_constants:
     613fraction_constants_opt:
    610614        // empty
    611615                { $$ = nullptr; }
    612         | fraction_constants FLOATING_FRACTIONconstant
     616        | fraction_constants_opt FLOATING_FRACTIONconstant
    613617                {
    614618                        Expression * constant = build_field_name_FLOATING_FRACTIONconstant( *$2 );
     
    23902394external_definition_list:
    23912395        external_definition
    2392         | external_definition_list { forall = xxx; } push external_definition
     2396        | external_definition_list
     2397                { forall = xxx; }
     2398          push external_definition
    23932399                { $$ = $1 ? $1->appendList( $4 ) : $4; }
    23942400        ;
     
    24302436                {
    24312437                        for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
    2432                                 iter->addQualifiers( $1->clone() );
     2438                                if ( isMangled( iter->linkage ) ) {             // ignore extern "C"
     2439                                        iter->addQualifiers( $1->clone() );
     2440                                } // if
    24332441                        } // for
    24342442                        xxx = false;
     
    24432451                {
    24442452                        for ( DeclarationNode * iter = $5; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
    2445                                 iter->addQualifiers( $1->clone() );
     2453                                if ( isMangled( iter->linkage ) ) {             // ignore extern "C"
     2454                                        iter->addQualifiers( $1->clone() );
     2455                                } // if
    24462456                        } // for
    24472457                        xxx = false;
     
    24572467                {
    24582468                        for ( DeclarationNode * iter = $6; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
    2459                                 iter->addQualifiers( $1->clone() );
    2460                                 iter->addQualifiers( $2->clone() );
     2469                                if ( isMangled( iter->linkage ) && isMangled( $2->linkage ) ) { // ignore extern "C"
     2470                                        iter->addQualifiers( $1->clone() );
     2471                                        iter->addQualifiers( $2->clone() );
     2472                                } // if
    24612473                        } // for
    24622474                        xxx = false;
  • src/benchmark/Makefile.am

    r7d0a3ba r358cba0  
    4343
    4444%.runquiet :
    45         @+make $(basename $@)
     45        @+make $(basename $@) CFLAGS="-w"
    4646        @taskset -c 1 ./a.out
    4747        @rm -f a.out
  • src/benchmark/Makefile.in

    r7d0a3ba r358cba0  
    459459
    460460%.runquiet :
    461         @+make $(basename $@)
     461        @+make $(basename $@) CFLAGS="-w"
    462462        @taskset -c 1 ./a.out
    463463        @rm -f a.out
  • src/driver/cc1.cc

    r7d0a3ba r358cba0  
    1010// Created On       : Fri Aug 26 14:23:51 2005
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jan 18 08:14:21 2017
    13 // Update Count     : 81
     12// Last Modified On : Sat May 12 16:11:53 2018
     13// Update Count     : 94
    1414//
    1515
     
    3232string compiler_name( CFA_BACKEND_CC );                                 // path/name of C compiler
    3333
     34string D__GCC_X__( "-D__GCC_X__=" );
    3435string D__GCC_BPREFIX__( "-D__GCC_BPREFIX__=" );
    3536string D__CFA_FLAGPREFIX__( "-D__CFA_FLAG__=" );
     
    162163                                cargs[ncargs] = ( *new string( string( argv[i + 1] ).substr( D__CFA_FLAGPREFIX__.size() - 2 ) ) ).c_str();
    163164                                ncargs += 1;
     165                                i += 1;                                                                 // and the argument
     166                        } else if ( prefix( arg, D__GCC_X__ ) ) {
     167                                args[nargs] = "-x";
     168                                nargs += 1;
     169                                args[nargs] = ( *new string( arg.substr( D__GCC_X__.size() ) ) ).c_str(); // pass the flag along
     170                                nargs += 1;
     171                        } else if ( arg == "-D" && prefix( argv[i + 1], D__GCC_X__.substr(2) ) ) {
     172                                args[nargs] = "-x";
     173                                nargs += 1;
     174                                args[nargs] = ( *new string( string( argv[i + 1] ).substr( D__GCC_X__.size() - 2 ) ) ).c_str(); // pass the flag along
     175                                nargs += 1;
    164176                                i += 1;                                                                 // and the argument
    165177                        } else if ( prefix( arg, D__GCC_BPREFIX__ ) ) {
  • src/driver/cfa.cc

    r7d0a3ba r358cba0  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May  2 17:57:43 2018
    13 // Update Count     : 224
     12// Last Modified On : Mon May 14 07:52:50 2018
     13// Update Count     : 243
    1414//
    1515
     
    158158                                args[nargs] = argv[i];                                  // pass the argument along
    159159                                nargs += 1;
    160                         } else if ( prefix( arg, "-std=" ) ) {
     160                        } else if ( prefix( arg, "-std=" ) || prefix( arg, "--std=" ) ) {
    161161                                std_flag = true;                                                // -std=XX provided
    162162                                args[nargs] = argv[i];                                  // pass the argument along
     163                                nargs += 1;
     164                        } else if ( arg == "-x" ) {                                     // lost so force along
     165                                args[nargs] = argv[i];                                  // pass the argument along
     166                                nargs += 1;
     167                                i += 1;                                                                 // advance to argument
     168                                args[nargs] = argv[i];                                  // pass the argument along
     169                                nargs += 1;
     170                                args[nargs] = ( *new string( string("-D__GCC_X__=") + argv[i] ) ).c_str(); // add the argument for -x
     171                                nargs += 1;
     172                        } else if ( prefix( arg, "-x" ) ) {                     // lost so force along
     173                                args[nargs] = argv[i];                                  // pass the argument along
     174                                nargs += 1;
     175                                args[nargs] = ( *new string( string("-D__GCC_X__=") + arg.substr(2) ) ).c_str(); // add the argument for -x
    163176                                nargs += 1;
    164177                        } else if ( arg == "-w" ) {
     
    240253        } // for
    241254
     255#ifdef __x86_64__
     256        args[nargs] = "-mcx16";                                                         // allow double-wide CAA
     257        nargs += 1;
     258#endif // __x86_64__
     259
    242260#ifdef __DEBUG_H__
    243261        cerr << "args:";
     
    268286        if ( link ) {
    269287                #if ! defined(HAVE_LIBCFA_RELEASE)
    270                         if( !debug ) {
     288                        if ( ! debug ) {
    271289                                cerr << "error: Option -nodebug is unavailable, libcfa was not installed." << endl;
    272290                                exit( EXIT_FAILURE );
    273                                 }
     291                        } // if
    274292                #endif
    275293                #if ! defined(HAVE_LIBCFA_DEBUG)
    276                         if( debug ) {
     294                        if ( debug ) {
    277295                                cerr << "error: Option -debug is unavailable, libcfa-d was not installed." << endl;
    278296                                exit( EXIT_FAILURE );
    279                                 }
     297                        } // if
    280298                #endif
    281299
     
    292310                args[nargs] = "-L" CFA_LIBDIR;
    293311                nargs += 1;
    294                 if( debug ) {
     312                if ( debug ) {
    295313                        args[nargs] = "-lcfa-d";
    296314                } else {
    297315                        args[nargs] = "-lcfa";
    298                 }
     316                } // if
    299317                nargs += 1;
    300318                args[nargs] = "-lpthread";
  • src/libcfa/bits/containers.h

    r7d0a3ba r358cba0  
    186186#endif
    187187
     188
     189//-----------------------------------------------------------------------------
     190// Doubly Linked List
     191//-----------------------------------------------------------------------------
     192#ifdef __cforall
     193        forall(dtype TYPE | sized(TYPE))
     194        #define T TYPE
     195        #define __getter_t * [T * & next, T * & prev] ( T & )
     196#else
     197        typedef void (*__generit_c_getter_t)();
     198        #define T void
     199        #define __getter_t __generit_c_getter_t
     200#endif
     201struct __dllist {
     202        T * head;
     203        __getter_t __get;
     204};
     205#undef T
     206#undef __getter_t
     207
     208#ifdef __cforall
     209#define __dllist_t(T) __dllist(T)
     210#else
     211#define __dllist_t(T) struct __dllist
     212#endif
     213
     214#ifdef __cforall
     215
     216        forall(dtype T | sized(T))
     217        static inline [void] ?{}( __dllist(T) & this, * [T * & next, T * & prev] ( T & ) __get ) {
     218                this.head{ NULL };
     219                this.__get = __get;
     220        }
     221
     222        #define _next .0
     223        #define _prev .1
     224        forall(dtype T | sized(T))
     225        static inline void push_front( __dllist(T) & this, T & node ) with( this ) {
     226                if ( head ) {
     227                        __get( node )_next = head;
     228                        __get( node )_prev = __get( *head )_prev;
     229                        // inserted node must be consistent before it is seen
     230                        // prevent code movement across barrier
     231                        asm( "" : : : "memory" );
     232                        __get( *head )_prev = &node;
     233                        T & prev = *__get( node )_prev;
     234                        __get( prev )_next = &node;
     235                }
     236                else {
     237                        __get( node )_next = &node;
     238                        __get( node )_prev = &node;
     239                }
     240
     241                // prevent code movement across barrier
     242                asm( "" : : : "memory" );
     243                head = &node;
     244        }
     245
     246        forall(dtype T | sized(T))
     247        static inline void remove( __dllist(T) & this, T & node ) with( this ) {
     248                if ( &node == head ) {
     249                        if ( __get( *head )_next == head ) {
     250                                head = NULL;
     251                        }
     252                        else {
     253                                head = __get( *head )_next;
     254                        }
     255                }
     256                __get( *__get( node )_next )_prev = __get( node )_prev;
     257                __get( *__get( node )_prev )_next = __get( node )_next;
     258                __get( node )_next = NULL;
     259                __get( node )_prev = NULL;
     260        }
     261        #undef _next
     262        #undef _prev
     263#endif
     264
    188265//-----------------------------------------------------------------------------
    189266// Tools
  • src/libcfa/concurrency/coroutine

    r7d0a3ba r358cba0  
    7272// Suspend implementation inlined for performance
    7373static inline void suspend() {
    74         coroutine_desc * src = TL_GET( this_coroutine );                        // optimization
     74        // optimization : read TLS once and reuse it
     75        // Safety note: this is preemption safe since if
     76        // preemption occurs after this line, the pointer
     77        // will also migrate which means this value will
     78        // stay in syn with the TLS
     79        coroutine_desc * src = TL_GET( this_coroutine );
    7580
    7681        assertf( src->last != 0,
     
    8994forall(dtype T | is_coroutine(T))
    9095static inline void resume(T & cor) {
    91         coroutine_desc * src = TL_GET( this_coroutine );                        // optimization
     96        // optimization : read TLS once and reuse it
     97        // Safety note: this is preemption safe since if
     98        // preemption occurs after this line, the pointer
     99        // will also migrate which means this value will
     100        // stay in syn with the TLS
     101        coroutine_desc * src = TL_GET( this_coroutine );
    92102        coroutine_desc * dst = get_coroutine(cor);
    93103
     
    107117                dst->last = src;
    108118                dst->starter = dst->starter ? dst->starter : src;
    109         } // if
     119        }
    110120
    111121        // always done for performance testing
     
    114124
    115125static inline void resume(coroutine_desc * dst) {
    116         coroutine_desc * src = TL_GET( this_coroutine );                        // optimization
     126        // optimization : read TLS once and reuse it
     127        // Safety note: this is preemption safe since if
     128        // preemption occurs after this line, the pointer
     129        // will also migrate which means this value will
     130        // stay in syn with the TLS
     131        coroutine_desc * src = TL_GET( this_coroutine );
    117132
    118133        // not resuming self ?
     
    125140                // set last resumer
    126141                dst->last = src;
    127         } // if
     142        }
    128143
    129144        // always done for performance testing
  • src/libcfa/concurrency/coroutine.c

    r7d0a3ba r358cba0  
    8484// Wrapper for co
    8585void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    86       verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
     86      // Safety note : This could cause some false positives due to preemption
     87      verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
    8788      disable_interrupts();
    8889
     
    9192
    9293      // set new coroutine that task is executing
    93       TL_SET( this_coroutine, dst );
     94      kernelTLS.this_coroutine = dst;
    9495
    9596      // context switch to specified coroutine
     
    102103
    103104      enable_interrupts( __cfaabi_dbg_ctx );
    104       verify( TL_GET( preemption_state ).enabled || TL_GET( this_processor )->do_terminate );
     105      // Safety note : This could cause some false positives due to preemption
     106      verify( TL_GET( preemption_state.enabled ) || TL_GET( this_processor )->do_terminate );
    105107} //ctxSwitchDirect
    106108
  • src/libcfa/concurrency/invoke.c

    r7d0a3ba r358cba0  
    6969        // Fetch the thread handle from the user defined thread structure
    7070        struct thread_desc* thrd = get_thread( this );
     71        thrd->self_cor.last = NULL;
    7172
    7273        // Officially start the thread by enabling preemption
  • src/libcfa/concurrency/invoke.h

    r7d0a3ba r358cba0  
    1818#include "bits/locks.h"
    1919
    20 #define TL_GET( member ) kernelThreadData.member
    21 #define TL_SET( member, value ) kernelThreadData.member = value;
     20#define TL_GET( member ) kernelTLS.member
     21#define TL_SET( member, value ) kernelTLS.member = value;
    2222
    2323#ifdef __cforall
     
    4444                                volatile bool in_progress;
    4545                        } preemption_state;
    46                 } kernelThreadData;
     46                } kernelTLS;
    4747        }
    4848
    4949        static inline struct coroutine_desc * volatile active_coroutine() { return TL_GET( this_coroutine ); }
    50         static inline struct thread_desc * volatile active_thread() { return TL_GET( this_thread ); }
    51         static inline struct processor * volatile active_processor() { return TL_GET( this_processor ); }
     50        static inline struct thread_desc    * volatile active_thread   () { return TL_GET( this_thread    ); }
     51        static inline struct processor      * volatile active_processor() { return TL_GET( this_processor ); } // UNSAFE
    5252        #endif
    5353
     
    136136                struct thread_desc * next;
    137137
    138                 __cfaabi_dbg_debug_do(
    139                         // instrusive link field for debugging
    140                         struct thread_desc * dbg_next;
    141                         struct thread_desc * dbg_prev;
    142                 )
     138                struct {
     139                        struct thread_desc * next;
     140                        struct thread_desc * prev;
     141                } node;
    143142     };
    144143
     
    147146                static inline thread_desc * & get_next( thread_desc & this ) {
    148147                        return this.next;
     148                }
     149
     150                static inline [thread_desc *&, thread_desc *& ] __get( thread_desc & this ) {
     151                        return this.node.[next, prev];
    149152                }
    150153
  • src/libcfa/concurrency/kernel

    r7d0a3ba r358cba0  
    4040
    4141//-----------------------------------------------------------------------------
    42 // Cluster
    43 struct cluster {
    44         // Ready queue locks
    45         __spinlock_t ready_queue_lock;
     42// Processor
     43extern struct cluster * mainCluster;
    4644
    47         // Ready queue for threads
    48         __queue_t(thread_desc) ready_queue;
    49 
    50         // Name of the cluster
    51         const char * name;
    52 
    53         // Preemption rate on this cluster
    54         Duration preemption_rate;
    55 };
    56 
    57 extern struct cluster * mainCluster;
    58 extern Duration default_preemption();
    59 
    60 void ?{} (cluster & this, const char * name, Duration preemption_rate);
    61 void ^?{}(cluster & this);
    62 
    63 static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
    64 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }
    65 static inline void ?{} (cluster & this, const char * name)        { this{name, default_preemption()}; }
    66 
    67 //-----------------------------------------------------------------------------
    68 // Processor
    6945enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule };
    7046
     
    9874
    9975        // Cluster from which to get threads
    100         cluster * cltr;
     76        struct cluster * cltr;
    10177
    10278        // Name of the processor
     
    124100        bool pending_preemption;
    125101
     102        // Idle lock
     103
     104        // Link lists fields
     105        struct {
     106                struct processor * next;
     107                struct processor * prev;
     108        } node;
     109
    126110#ifdef __CFA_DEBUG__
    127111        // Last function to enable preemption on this processor
     
    130114};
    131115
    132 void  ?{}(processor & this, const char * name, cluster & cltr);
     116void  ?{}(processor & this, const char * name, struct cluster & cltr);
    133117void ^?{}(processor & this);
    134118
    135119static inline void  ?{}(processor & this)                    { this{ "Anonymous Processor", *mainCluster}; }
    136 static inline void  ?{}(processor & this, cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
     120static inline void  ?{}(processor & this, struct cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
    137121static inline void  ?{}(processor & this, const char * name) { this{name, *mainCluster }; }
     122
     123static inline [processor *&, processor *& ] __get( processor & this ) {
     124        return this.node.[next, prev];
     125}
     126
     127//-----------------------------------------------------------------------------
     128// Cluster
     129struct cluster {
     130        // Ready queue locks
     131        __spinlock_t ready_queue_lock;
     132
     133        // Ready queue for threads
     134        __queue_t(thread_desc) ready_queue;
     135
     136        // Name of the cluster
     137        const char * name;
     138
     139        // Preemption rate on this cluster
     140        Duration preemption_rate;
     141
     142        // List of processors
     143        __spinlock_t proc_list_lock;
     144        __dllist_t(struct processor) procs;
     145        __dllist_t(struct processor) idles;
     146
     147        // Link lists fields
     148        struct {
     149                cluster * next;
     150                cluster * prev;
     151        } node;
     152};
     153extern Duration default_preemption();
     154
     155void ?{} (cluster & this, const char * name, Duration preemption_rate);
     156void ^?{}(cluster & this);
     157
     158static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
     159static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }
     160static inline void ?{} (cluster & this, const char * name)        { this{name, default_preemption()}; }
     161
     162static inline [cluster *&, cluster *& ] __get( cluster & this ) {
     163        return this.node.[next, prev];
     164}
    138165
    139166// Local Variables: //
  • src/libcfa/concurrency/kernel.c

    r7d0a3ba r358cba0  
    4949thread_desc * mainThread;
    5050
     51struct { __dllist_t(thread_desc) list; __spinlock_t lock; } global_threads ;
     52struct { __dllist_t(cluster    ) list; __spinlock_t lock; } global_clusters;
     53
    5154//-----------------------------------------------------------------------------
    5255// Global state
     
    5659// volatile thread_local unsigned short disable_preempt_count = 1;
    5760
    58 thread_local struct KernelThreadData kernelThreadData = {
     61thread_local struct KernelThreadData kernelTLS = {
    5962        NULL,
    6063        NULL,
     
    117120        self_mon_p = &self_mon;
    118121        next = NULL;
    119         __cfaabi_dbg_debug_do(
    120                 dbg_next = NULL;
    121                 dbg_prev = NULL;
    122                 __cfaabi_dbg_thread_register(&this);
    123         )
     122
     123        node.next = NULL;
     124        node.prev = NULL;
     125        doregister(this);
    124126
    125127        monitors{ &self_mon_p, 1, (fptr_t)0 };
     
    155157                terminate(&this);
    156158                verify(this.do_terminate);
    157                 verify(TL_GET( this_processor ) != &this);
     159                verify( kernelTLS.this_processor != &this);
    158160                P( terminated );
    159                 verify(TL_GET( this_processor ) != &this);
     161                verify( kernelTLS.this_processor != &this);
    160162                pthread_join( kernel_thread, NULL );
    161163        }
     
    167169        ready_queue{};
    168170        ready_queue_lock{};
     171
     172        procs{ __get };
     173        idles{ __get };
     174
     175        doregister(this);
    169176}
    170177
    171178void ^?{}(cluster & this) {
    172 
     179        unregister(this);
    173180}
    174181
     
    183190        __cfaabi_dbg_print_safe("Kernel : core %p starting\n", this);
    184191
     192        doregister(this->cltr, this);
     193
    185194        {
    186195                // Setup preemption data
     
    196205                        if(readyThread)
    197206                        {
    198                                 verify( ! TL_GET( preemption_state ).enabled );
     207                                verify( ! kernelTLS.preemption_state.enabled );
    199208
    200209                                runThread(this, readyThread);
    201210
    202                                 verify( ! TL_GET( preemption_state ).enabled );
     211                                verify( ! kernelTLS.preemption_state.enabled );
    203212
    204213                                //Some actions need to be taken from the kernel
     
    216225        }
    217226
     227        unregister(this->cltr, this);
     228
    218229        V( this->terminated );
    219230
     
    221232}
    222233
     234// KERNEL ONLY
    223235// runThread runs a thread by context switching
    224236// from the processor coroutine to the target thread
     
    228240        coroutine_desc * thrd_cor = dst->curr_cor;
    229241
    230         //Reset the terminating actions here
     242        // Reset the terminating actions here
    231243        this->finish.action_code = No_Action;
    232244
    233         //Update global state
    234         TL_SET( this_thread, dst );
     245        // Update global state
     246        kernelTLS.this_thread = dst;
    235247
    236248        // Context Switch to the thread
     
    239251}
    240252
     253// KERNEL_ONLY
    241254void returnToKernel() {
    242         coroutine_desc * proc_cor = get_coroutine(TL_GET( this_processor )->runner);
    243         coroutine_desc * thrd_cor = TL_GET( this_thread )->curr_cor = TL_GET( this_coroutine );
     255        coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
     256        coroutine_desc * thrd_cor = kernelTLS.this_thread->curr_cor = kernelTLS.this_coroutine;
    244257        ThreadCtxSwitch(thrd_cor, proc_cor);
    245258}
    246259
     260// KERNEL_ONLY
    247261// Once a thread has finished running, some of
    248262// its final actions must be executed from the kernel
    249263void finishRunning(processor * this) with( this->finish ) {
    250264        if( action_code == Release ) {
    251                 verify( ! TL_GET( preemption_state ).enabled );
     265                verify( ! kernelTLS.preemption_state.enabled );
    252266                unlock( *lock );
    253267        }
     
    256270        }
    257271        else if( action_code == Release_Schedule ) {
    258                 verify( ! TL_GET( preemption_state ).enabled );
     272                verify( ! kernelTLS.preemption_state.enabled );
    259273                unlock( *lock );
    260274                ScheduleThread( thrd );
    261275        }
    262276        else if( action_code == Release_Multi ) {
    263                 verify( ! TL_GET( preemption_state ).enabled );
     277                verify( ! kernelTLS.preemption_state.enabled );
    264278                for(int i = 0; i < lock_count; i++) {
    265279                        unlock( *locks[i] );
     
    285299}
    286300
     301// KERNEL_ONLY
    287302// Context invoker for processors
    288303// This is the entry point for processors (kernel threads)
     
    290305void * CtxInvokeProcessor(void * arg) {
    291306        processor * proc = (processor *) arg;
    292         TL_SET( this_processor, proc );
    293         TL_SET( this_coroutine, NULL );
    294         TL_SET( this_thread, NULL );
    295         TL_GET( preemption_state ).[enabled, disable_count] = [false, 1];
     307        kernelTLS.this_processor = proc;
     308        kernelTLS.this_coroutine = NULL;
     309        kernelTLS.this_thread    = NULL;
     310        kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
    296311        // SKULLDUGGERY: We want to create a context for the processor coroutine
    297312        // which is needed for the 2-step context switch. However, there is no reason
     
    305320
    306321        //Set global state
    307         TL_SET( this_coroutine, get_coroutine(proc->runner) );
    308         TL_SET( this_thread, NULL );
     322        kernelTLS.this_coroutine = get_coroutine(proc->runner);
     323        kernelTLS.this_thread    = NULL;
    309324
    310325        //We now have a proper context from which to schedule threads
     
    333348}
    334349
     350// KERNEL_ONLY
    335351void kernel_first_resume(processor * this) {
    336         coroutine_desc * src = TL_GET( this_coroutine );
     352        coroutine_desc * src = kernelTLS.this_coroutine;
    337353        coroutine_desc * dst = get_coroutine(this->runner);
    338354
    339         verify( ! TL_GET( preemption_state ).enabled );
     355        verify( ! kernelTLS.preemption_state.enabled );
    340356
    341357        create_stack(&dst->stack, dst->stack.size);
    342358        CtxStart(&this->runner, CtxInvokeCoroutine);
    343359
    344         verify( ! TL_GET( preemption_state ).enabled );
     360        verify( ! kernelTLS.preemption_state.enabled );
    345361
    346362        dst->last = src;
     
    351367
    352368        // set new coroutine that task is executing
    353         TL_SET( this_coroutine, dst );
     369        kernelTLS.this_coroutine = dst;
    354370
    355371        // SKULLDUGGERY normally interrupts are enable before leaving a coroutine ctxswitch.
     
    368384        src->state = Active;
    369385
    370         verify( ! TL_GET( preemption_state ).enabled );
     386        verify( ! kernelTLS.preemption_state.enabled );
    371387}
    372388
    373389//-----------------------------------------------------------------------------
    374390// Scheduler routines
     391
     392// KERNEL ONLY
    375393void ScheduleThread( thread_desc * thrd ) {
    376         // if( ! thrd ) return;
    377394        verify( thrd );
    378395        verify( thrd->self_cor.state != Halted );
    379396
    380         verify( ! TL_GET( preemption_state ).enabled );
     397        verify( ! kernelTLS.preemption_state.enabled );
    381398
    382399        verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
     
    388405        }
    389406
    390         verify( ! TL_GET( preemption_state ).enabled );
    391 }
    392 
     407        verify( ! kernelTLS.preemption_state.enabled );
     408}
     409
     410// KERNEL ONLY
    393411thread_desc * nextThread(cluster * this) with( *this ) {
    394         verify( ! TL_GET( preemption_state ).enabled );
     412        verify( ! kernelTLS.preemption_state.enabled );
    395413        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
    396414        thread_desc * head = pop_head( ready_queue );
    397415        unlock( ready_queue_lock );
    398         verify( ! TL_GET( preemption_state ).enabled );
     416        verify( ! kernelTLS.preemption_state.enabled );
    399417        return head;
    400418}
     
    402420void BlockInternal() {
    403421        disable_interrupts();
    404         verify( ! TL_GET( preemption_state ).enabled );
     422        verify( ! kernelTLS.preemption_state.enabled );
    405423        returnToKernel();
    406         verify( ! TL_GET( preemption_state ).enabled );
     424        verify( ! kernelTLS.preemption_state.enabled );
    407425        enable_interrupts( __cfaabi_dbg_ctx );
    408426}
     
    410428void BlockInternal( __spinlock_t * lock ) {
    411429        disable_interrupts();
    412         with( *TL_GET( this_processor ) ) {
     430        with( *kernelTLS.this_processor ) {
    413431                finish.action_code = Release;
    414432                finish.lock        = lock;
    415433        }
    416434
    417         verify( ! TL_GET( preemption_state ).enabled );
     435        verify( ! kernelTLS.preemption_state.enabled );
    418436        returnToKernel();
    419         verify( ! TL_GET( preemption_state ).enabled );
     437        verify( ! kernelTLS.preemption_state.enabled );
    420438
    421439        enable_interrupts( __cfaabi_dbg_ctx );
     
    424442void BlockInternal( thread_desc * thrd ) {
    425443        disable_interrupts();
    426         with( *TL_GET( this_processor ) ) {
     444        with( * kernelTLS.this_processor ) {
    427445                finish.action_code = Schedule;
    428446                finish.thrd        = thrd;
    429447        }
    430448
    431         verify( ! TL_GET( preemption_state ).enabled );
     449        verify( ! kernelTLS.preemption_state.enabled );
    432450        returnToKernel();
    433         verify( ! TL_GET( preemption_state ).enabled );
     451        verify( ! kernelTLS.preemption_state.enabled );
    434452
    435453        enable_interrupts( __cfaabi_dbg_ctx );
     
    439457        assert(thrd);
    440458        disable_interrupts();
    441         with( *TL_GET( this_processor ) ) {
     459        with( * kernelTLS.this_processor ) {
    442460                finish.action_code = Release_Schedule;
    443461                finish.lock        = lock;
     
    445463        }
    446464
    447         verify( ! TL_GET( preemption_state ).enabled );
     465        verify( ! kernelTLS.preemption_state.enabled );
    448466        returnToKernel();
    449         verify( ! TL_GET( preemption_state ).enabled );
     467        verify( ! kernelTLS.preemption_state.enabled );
    450468
    451469        enable_interrupts( __cfaabi_dbg_ctx );
     
    454472void BlockInternal(__spinlock_t * locks [], unsigned short count) {
    455473        disable_interrupts();
    456         with( *TL_GET( this_processor ) ) {
     474        with( * kernelTLS.this_processor ) {
    457475                finish.action_code = Release_Multi;
    458476                finish.locks       = locks;
     
    460478        }
    461479
    462         verify( ! TL_GET( preemption_state ).enabled );
     480        verify( ! kernelTLS.preemption_state.enabled );
    463481        returnToKernel();
    464         verify( ! TL_GET( preemption_state ).enabled );
     482        verify( ! kernelTLS.preemption_state.enabled );
    465483
    466484        enable_interrupts( __cfaabi_dbg_ctx );
     
    469487void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {
    470488        disable_interrupts();
    471         with( *TL_GET( this_processor ) ) {
     489        with( *kernelTLS.this_processor ) {
    472490                finish.action_code = Release_Multi_Schedule;
    473491                finish.locks       = locks;
     
    477495        }
    478496
    479         verify( ! TL_GET( preemption_state ).enabled );
     497        verify( ! kernelTLS.preemption_state.enabled );
    480498        returnToKernel();
    481         verify( ! TL_GET( preemption_state ).enabled );
     499        verify( ! kernelTLS.preemption_state.enabled );
    482500
    483501        enable_interrupts( __cfaabi_dbg_ctx );
    484502}
    485503
     504// KERNEL ONLY
    486505void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
    487         verify( ! TL_GET( preemption_state ).enabled );
    488         with( *TL_GET( this_processor ) ) {
     506        verify( ! kernelTLS.preemption_state.enabled );
     507        with( * kernelTLS.this_processor ) {
    489508                finish.action_code = thrd ? Release_Schedule : Release;
    490509                finish.lock        = lock;
     
    501520// Kernel boot procedures
    502521void kernel_startup(void) {
    503         verify( ! TL_GET( preemption_state ).enabled );
     522        verify( ! kernelTLS.preemption_state.enabled );
    504523        __cfaabi_dbg_print_safe("Kernel : Starting\n");
     524
     525        global_threads. list{ __get };
     526        global_threads. lock{};
     527        global_clusters.list{ __get };
     528        global_clusters.lock{};
    505529
    506530        // Initialize the main cluster
     
    547571
    548572        //initialize the global state variables
    549         TL_SET( this_processor, mainProcessor );
    550         TL_SET( this_thread, mainThread );
    551         TL_SET( this_coroutine, &mainThread->self_cor );
     573        kernelTLS.this_processor = mainProcessor;
     574        kernelTLS.this_thread    = mainThread;
     575        kernelTLS.this_coroutine = &mainThread->self_cor;
    552576
    553577        // Enable preemption
     
    561585        // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
    562586        // mainThread is on the ready queue when this call is made.
    563         kernel_first_resume( TL_GET( this_processor ) );
     587        kernel_first_resume( kernelTLS.this_processor );
    564588
    565589
     
    568592        __cfaabi_dbg_print_safe("Kernel : Started\n--------------------------------------------------\n\n");
    569593
    570         verify( ! TL_GET( preemption_state ).enabled );
     594        verify( ! kernelTLS.preemption_state.enabled );
    571595        enable_interrupts( __cfaabi_dbg_ctx );
    572         verify( TL_GET( preemption_state ).enabled );
     596        verify( TL_GET( preemption_state.enabled ) );
    573597}
    574598
     
    576600        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    577601
    578         verify( TL_GET( preemption_state ).enabled );
     602        verify( TL_GET( preemption_state.enabled ) );
    579603        disable_interrupts();
    580         verify( ! TL_GET( preemption_state ).enabled );
     604        verify( ! kernelTLS.preemption_state.enabled );
    581605
    582606        // SKULLDUGGERY: Notify the mainProcessor it needs to terminates.
     
    604628
    605629//=============================================================================================
     630// Kernel Quiescing
     631//=============================================================================================
     632
     633// void halt(processor * this) with( this ) {
     634//      pthread_mutex_lock( &idle.lock );
     635
     636
     637
     638//      // SKULLDUGGERY: Even if spurious wake-up is a thing
     639//      // spuriously waking up a kernel thread is not a big deal
     640//      // if it is very rare.
     641//      pthread_cond_wait( &idle.cond, &idle.lock);
     642//      pthread_mutex_unlock( &idle.lock );
     643// }
     644
     645// void wake(processor * this) with( this ) {
     646//      pthread_mutex_lock  (&idle.lock);
     647//      pthread_cond_signal (&idle.cond);
     648//      pthread_mutex_unlock(&idle.lock);
     649// }
     650
     651//=============================================================================================
    606652// Unexpected Terminating logic
    607653//=============================================================================================
     
    609655
    610656static __spinlock_t kernel_abort_lock;
    611 static __spinlock_t kernel_debug_lock;
    612657static bool kernel_abort_called = false;
    613658
    614 void * kernel_abort    (void) __attribute__ ((__nothrow__)) {
     659void * kernel_abort(void) __attribute__ ((__nothrow__)) {
    615660        // abort cannot be recursively entered by the same or different processors because all signal handlers return when
    616661        // the globalAbort flag is true.
     
    618663
    619664        // first task to abort ?
    620         if ( ! kernel_abort_called ) {                  // not first task to abort ?
     665        if ( kernel_abort_called ) {                    // not first task to abort ?
     666                unlock( kernel_abort_lock );
     667
     668                sigset_t mask;
     669                sigemptyset( &mask );
     670                sigaddset( &mask, SIGALRM );            // block SIGALRM signals
     671                sigsuspend( &mask );                    // block the processor to prevent further damage during abort
     672                _exit( EXIT_FAILURE );                  // if processor unblocks before it is killed, terminate it
     673        }
     674        else {
    621675                kernel_abort_called = true;
    622676                unlock( kernel_abort_lock );
    623677        }
    624         else {
    625                 unlock( kernel_abort_lock );
    626 
    627                 sigset_t mask;
    628                 sigemptyset( &mask );
    629                 sigaddset( &mask, SIGALRM );                    // block SIGALRM signals
    630                 sigaddset( &mask, SIGUSR1 );                    // block SIGUSR1 signals
    631                 sigsuspend( &mask );                            // block the processor to prevent further damage during abort
    632                 _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
    633         }
    634 
    635         return TL_GET( this_thread );
     678
     679        return kernelTLS.this_thread;
    636680}
    637681
     
    639683        thread_desc * thrd = kernel_data;
    640684
    641         int len = snprintf( abort_text, abort_text_size, "Error occurred while executing task %.256s (%p)", thrd->self_cor.name, thrd );
    642         __cfaabi_dbg_bits_write( abort_text, len );
    643 
    644         if ( get_coroutine(thrd) != TL_GET( this_coroutine ) ) {
    645                 len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", TL_GET( this_coroutine )->name, TL_GET( this_coroutine ) );
     685        if(thrd) {
     686                int len = snprintf( abort_text, abort_text_size, "Error occurred while executing thread %.256s (%p)", thrd->self_cor.name, thrd );
    646687                __cfaabi_dbg_bits_write( abort_text, len );
     688
     689                if ( get_coroutine(thrd) != kernelTLS.this_coroutine ) {
     690                        len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", kernelTLS.this_coroutine->name, kernelTLS.this_coroutine );
     691                        __cfaabi_dbg_bits_write( abort_text, len );
     692                }
     693                else {
     694                        __cfaabi_dbg_bits_write( ".\n", 2 );
     695                }
    647696        }
    648697        else {
    649                 __cfaabi_dbg_bits_write( ".\n", 2 );
     698                int len = snprintf( abort_text, abort_text_size, "Error occurred outside of any thread.\n" );
    650699        }
    651700}
    652701
    653702int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__)) {
    654         return get_coroutine(TL_GET( this_thread )) == get_coroutine(mainThread) ? 4 : 2;
    655 }
     703        return get_coroutine(kernelTLS.this_thread) == get_coroutine(mainThread) ? 4 : 2;
     704}
     705
     706static __spinlock_t kernel_debug_lock;
    656707
    657708extern "C" {
     
    682733        if ( count < 0 ) {
    683734                // queue current task
    684                 append( waiting, (thread_desc *)TL_GET( this_thread ) );
     735                append( waiting, kernelTLS.this_thread );
    685736
    686737                // atomically release spin lock and block
     
    708759
    709760//-----------------------------------------------------------------------------
     761// Global Queues
     762void doregister( thread_desc & thrd ) {
     763        // lock      ( global_thread.lock );
     764        // push_front( global_thread.list, thrd );
     765        // unlock    ( global_thread.lock );
     766}
     767
     768void unregister( thread_desc & thrd ) {
     769        // lock  ( global_thread.lock );
     770        // remove( global_thread.list, thrd );
     771        // unlock( global_thread.lock );
     772}
     773
     774void doregister( cluster     & cltr ) {
     775        // lock      ( global_cluster.lock );
     776        // push_front( global_cluster.list, cltr );
     777        // unlock    ( global_cluster.lock );
     778}
     779
     780void unregister( cluster     & cltr ) {
     781        // lock  ( global_cluster.lock );
     782        // remove( global_cluster.list, cltr );
     783        // unlock( global_cluster.lock );
     784}
     785
     786
     787void doregister( cluster * cltr, processor * proc ) {
     788        // lock      (cltr->proc_list_lock __cfaabi_dbg_ctx2);
     789        // push_front(cltr->procs, *proc);
     790        // unlock    (cltr->proc_list_lock);
     791}
     792
     793void unregister( cluster * cltr, processor * proc ) {
     794        // lock  (cltr->proc_list_lock __cfaabi_dbg_ctx2);
     795        // remove(cltr->procs, *proc );
     796        // unlock(cltr->proc_list_lock);
     797}
     798
     799//-----------------------------------------------------------------------------
    710800// Debug
    711801__cfaabi_dbg_debug_do(
    712         struct {
    713                 thread_desc * tail;
    714         } __cfaabi_dbg_thread_list = { NULL };
    715 
    716         void __cfaabi_dbg_thread_register( thread_desc * thrd ) {
    717                 if( !__cfaabi_dbg_thread_list.tail ) {
    718                         __cfaabi_dbg_thread_list.tail = thrd;
    719                         return;
    720                 }
    721                 __cfaabi_dbg_thread_list.tail->dbg_next = thrd;
    722                 thrd->dbg_prev = __cfaabi_dbg_thread_list.tail;
    723                 __cfaabi_dbg_thread_list.tail = thrd;
    724         }
    725 
    726         void __cfaabi_dbg_thread_unregister( thread_desc * thrd ) {
    727                 thread_desc * prev = thrd->dbg_prev;
    728                 thread_desc * next = thrd->dbg_next;
    729 
    730                 if( next ) { next->dbg_prev = prev; }
    731                 else       {
    732                         assert( __cfaabi_dbg_thread_list.tail == thrd );
    733                         __cfaabi_dbg_thread_list.tail = prev;
    734                 }
    735 
    736                 if( prev ) { prev->dbg_next = next; }
    737 
    738                 thrd->dbg_prev = NULL;
    739                 thrd->dbg_next = NULL;
    740         }
    741 
    742802        void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {
    743803                this.prev_name = prev_name;
    744                 this.prev_thrd = TL_GET( this_thread );
     804                this.prev_thrd = kernelTLS.this_thread;
    745805        }
    746806)
  • src/libcfa/concurrency/kernel_private.h

    r7d0a3ba r358cba0  
    100100#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
    101101
     102
     103void doregister( struct thread_desc & thrd );
     104void unregister( struct thread_desc & thrd );
     105
     106void doregister( struct cluster     & cltr );
     107void unregister( struct cluster     & cltr );
     108
     109void doregister( struct cluster * cltr, struct processor * proc );
     110void unregister( struct cluster * cltr, struct processor * proc );
     111
    102112// Local Variables: //
    103113// mode: c //
  • src/libcfa/concurrency/monitor.c

    r7d0a3ba r358cba0  
    8585                // Lock the monitor spinlock
    8686                lock( this->lock __cfaabi_dbg_ctx2 );
    87                 thread_desc * thrd = TL_GET( this_thread );
     87                // Interrupts disable inside critical section
     88                thread_desc * thrd = kernelTLS.this_thread;
    8889
    8990                __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
     
    134135                // Lock the monitor spinlock
    135136                lock( this->lock __cfaabi_dbg_ctx2 );
    136                 thread_desc * thrd = TL_GET( this_thread );
     137                // Interrupts disable inside critical section
     138                thread_desc * thrd = kernelTLS.this_thread;
    137139
    138140                __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     
    168170
    169171                        // Create the node specific to this wait operation
    170                         wait_ctx_primed( TL_GET( this_thread ), 0 )
     172                        wait_ctx_primed( thrd, 0 )
    171173
    172174                        // Some one else has the monitor, wait for him to finish and then run
     
    179181                        __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
    180182
    181                         wait_ctx( TL_GET( this_thread ), 0 )
     183                        wait_ctx( thrd, 0 )
    182184                        this->dtor_node = &waiter;
    183185
     
    199201                lock( this->lock __cfaabi_dbg_ctx2 );
    200202
    201                 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", TL_GET( this_thread ), this, this->owner);
    202 
    203                 verifyf( TL_GET( this_thread ) == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", TL_GET( this_thread ), this->owner, this->recursion, this );
     203                __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);
     204
     205                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 );
    204206
    205207                // Leaving a recursion level, decrement the counter
     
    289291// Sorts monitors before entering
    290292void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) {
     293        thread_desc * thrd = TL_GET( this_thread );
     294
    291295        // Store current array
    292296        this.m = m;
     
    297301
    298302        // Save previous thread context
    299         this.prev = TL_GET( this_thread )->monitors;
     303        this.prev = thrd->monitors;
    300304
    301305        // Update thread context (needed for conditions)
    302         (TL_GET( this_thread )->monitors){m, count, func};
     306        (thrd->monitors){m, count, func};
    303307
    304308        // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count);
     
    328332// Sorts monitors before entering
    329333void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) {
     334        // optimization
     335        thread_desc * thrd = TL_GET( this_thread );
     336
    330337        // Store current array
    331338        this.m = *m;
    332339
    333340        // Save previous thread context
    334         this.prev = TL_GET( this_thread )->monitors;
     341        this.prev = thrd->monitors;
    335342
    336343        // Update thread context (needed for conditions)
    337         (TL_GET( this_thread )->monitors){m, 1, func};
     344        (thrd->monitors){m, 1, func};
    338345
    339346        __enter_monitor_dtor( this.m, func );
     
    473480
    474481        // Create the node specific to this wait operation
    475         wait_ctx_primed( TL_GET( this_thread ), 0 )
     482        wait_ctx_primed( kernelTLS.this_thread, 0 )
    476483
    477484        //save contexts
     
    566573
    567574                                // Create the node specific to this wait operation
    568                                 wait_ctx_primed( TL_GET( this_thread ), 0 );
     575                                wait_ctx_primed( kernelTLS.this_thread, 0 );
    569576
    570577                                // Save monitor states
     
    612619
    613620        // Create the node specific to this wait operation
    614         wait_ctx_primed( TL_GET( this_thread ), 0 );
     621        wait_ctx_primed( kernelTLS.this_thread, 0 );
    615622
    616623        monitor_save;
     
    618625
    619626        for( __lock_size_t i = 0; i < count; i++) {
    620                 verify( monitors[i]->owner == TL_GET( this_thread ) );
     627                verify( monitors[i]->owner == kernelTLS.this_thread );
    621628        }
    622629
  • src/libcfa/concurrency/preemption.c

    r7d0a3ba r358cba0  
    149149        // Disable interrupts by incrementing the counter
    150150        void disable_interrupts() {
    151                 with( TL_GET( preemption_state ) ) {
     151                with( kernelTLS.preemption_state ) {
    152152                        enabled = false;
    153153                        __attribute__((unused)) unsigned short new_val = disable_count + 1;
     
    160160        // If counter reaches 0, execute any pending CtxSwitch
    161161        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    162                 processor   * proc = TL_GET( this_processor ); // Cache the processor now since interrupts can start happening after the atomic add
    163                 thread_desc * thrd = TL_GET( this_thread );       // Cache the thread now since interrupts can start happening after the atomic add
    164 
    165                 with( TL_GET( preemption_state ) ){
     162                processor   * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic add
     163                thread_desc * thrd = kernelTLS.this_thread;       // Cache the thread now since interrupts can start happening after the atomic add
     164
     165                with( kernelTLS.preemption_state ){
    166166                        unsigned short prev = disable_count;
    167167                        disable_count -= 1;
     
    185185        // Don't execute any pending CtxSwitch even if counter reaches 0
    186186        void enable_interrupts_noPoll() {
    187                 unsigned short prev = TL_GET( preemption_state ).disable_count;
    188                 TL_GET( preemption_state ).disable_count -= 1;
     187                unsigned short prev = kernelTLS.preemption_state.disable_count;
     188                kernelTLS.preemption_state.disable_count -= 1;
    189189                verifyf( prev != 0u, "Incremented from %u\n", prev );                     // If this triggers someone is enabled already enabled interrupts
    190190                if( prev == 1 ) {
    191                         TL_GET( preemption_state ).enabled = true;
     191                        kernelTLS.preemption_state.enabled = true;
    192192                }
    193193        }
     
    234234}
    235235
    236 
     236// KERNEL ONLY
    237237// Check if a CtxSwitch signal handler shoud defer
    238238// If true  : preemption is safe
    239239// If false : preemption is unsafe and marked as pending
    240240static inline bool preemption_ready() {
    241         bool ready = TL_GET( preemption_state ).enabled && !TL_GET( preemption_state ).in_progress; // Check if preemption is safe
    242         TL_GET( this_processor )->pending_preemption = !ready;                  // Adjust the pending flag accordingly
     241        // Check if preemption is safe
     242        bool ready = kernelTLS.preemption_state.enabled && ! kernelTLS.preemption_state.in_progress;
     243
     244        // Adjust the pending flag accordingly
     245        kernelTLS.this_processor->pending_preemption = !ready;
    243246        return ready;
    244247}
     
    254257
    255258        // Start with preemption disabled until ready
    256         TL_GET( preemption_state ).enabled = false;
    257         TL_GET( preemption_state ).disable_count = 1;
     259        kernelTLS.preemption_state.enabled = false;
     260        kernelTLS.preemption_state.disable_count = 1;
    258261
    259262        // Initialize the event kernel
     
    320323        // before the kernel thread has even started running. When that happens an iterrupt
    321324        // we a null 'this_processor' will be caught, just ignore it.
    322         if(!TL_GET( this_processor )) return;
     325        if(! kernelTLS.this_processor ) return;
    323326
    324327        choose(sfp->si_value.sival_int) {
    325328                case PREEMPT_NORMAL   : ;// Normal case, nothing to do here
    326                 case PREEMPT_TERMINATE: verify(TL_GET( this_processor )->do_terminate);
     329                case PREEMPT_TERMINATE: verify( kernelTLS.this_processor->do_terminate);
    327330                default:
    328331                        abort( "internal error, signal value is %d", sfp->si_value.sival_int );
     
    332335        if( !preemption_ready() ) { return; }
    333336
    334         __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", TL_GET( this_processor ), TL_GET( this_thread ) );
    335 
    336         TL_GET( preemption_state ).in_progress = true;  // Sync flag : prevent recursive calls to the signal handler
    337         signal_unblock( SIGUSR1 );                          // We are about to CtxSwitch out of the signal handler, let other handlers in
    338         TL_GET( preemption_state ).in_progress = false; // Clear the in progress flag
     337        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", kernelTLS.this_processor, kernelTLS.this_thread );
     338
     339        // Sync flag : prevent recursive calls to the signal handler
     340        kernelTLS.preemption_state.in_progress = true;
     341
     342        // We are about to CtxSwitch out of the signal handler, let other handlers in
     343        signal_unblock( SIGUSR1 );
     344
     345        // TODO: this should go in finish action
     346        // Clear the in progress flag
     347        kernelTLS.preemption_state.in_progress = false;
    339348
    340349        // Preemption can occur here
    341350
    342         BlockInternal( (thread_desc*)TL_GET( this_thread ) ); // Do the actual CtxSwitch
     351        BlockInternal( kernelTLS.this_thread ); // Do the actual CtxSwitch
    343352}
    344353
     
    348357        // Block sigalrms to control when they arrive
    349358        sigset_t mask;
     359        sigfillset(&mask);
     360        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     361            abort( "internal error, pthread_sigmask" );
     362        }
     363
    350364        sigemptyset( &mask );
    351365        sigaddset( &mask, SIGALRM );
    352 
    353         if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
    354             abort( "internal error, pthread_sigmask" );
    355         }
    356366
    357367        // Main loop
     
    409419
    410420void __cfaabi_check_preemption() {
    411         bool ready = TL_GET( preemption_state ).enabled;
     421        bool ready = kernelTLS.preemption_state.enabled;
    412422        if(!ready) { abort("Preemption should be ready"); }
    413423
  • src/libcfa/concurrency/thread.c

    r7d0a3ba r358cba0  
    3939        curr_cluster = &cl;
    4040        next = NULL;
    41         __cfaabi_dbg_debug_do(
    42                 dbg_next = NULL;
    43                 dbg_prev = NULL;
    44                 __cfaabi_dbg_thread_register(&this);
    45         )
     41
     42        node.next = NULL;
     43        node.prev = NULL;
     44        doregister(this);
    4645
    4746        monitors{ &self_mon_p, 1, (fptr_t)0 };
     
    4948
    5049void ^?{}(thread_desc& this) with( this ) {
     50        unregister(this);
    5151        ^self_cor{};
    5252}
     
    8181        disable_interrupts();
    8282        create_stack(&thrd_c->stack, thrd_c->stack.size);
    83         TL_SET( this_coroutine, thrd_c );
     83        kernelTLS.this_coroutine = thrd_c;
    8484        CtxStart(&this, CtxInvokeThread);
    8585        assert( thrd_c->last->stack.context );
     
    9191
    9292extern "C" {
     93        // KERNEL ONLY
    9394        void __finish_creation(void) {
    94                 coroutine_desc* thrd_c = TL_GET( this_coroutine );
     95                coroutine_desc* thrd_c = kernelTLS.this_coroutine;
    9596                ThreadCtxSwitch( thrd_c, thrd_c->last );
    9697        }
     
    9899
    99100void yield( void ) {
    100         verify( TL_GET( preemption_state ).enabled );
     101        // Safety note : This could cause some false positives due to preemption
     102      verify( TL_GET( preemption_state.enabled ) );
    101103        BlockInternal( TL_GET( this_thread ) );
    102         verify( TL_GET( preemption_state ).enabled );
     104        // Safety note : This could cause some false positives due to preemption
     105      verify( TL_GET( preemption_state.enabled ) );
    103106}
    104107
     
    109112}
    110113
     114// KERNEL ONLY
    111115void ThreadCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    112116        // set state of current coroutine to inactive
     
    116120        // set new coroutine that the processor is executing
    117121        // and context switch to it
    118         TL_SET( this_coroutine, dst );
     122        kernelTLS.this_coroutine = dst;
    119123        assert( src->stack.context );
    120124        CtxSwitch( src->stack.context, dst->stack.context );
    121         TL_SET( this_coroutine, src );
     125        kernelTLS.this_coroutine = src;
    122126
    123127        // set state of new coroutine to active
  • src/libcfa/interpose.c

    r7d0a3ba r358cba0  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May  1 15:05:35 2018
    13 // Update Count     : 83
    14 //
    15 
    16 #include <stdarg.h>
    17 #include <stddef.h>
    18 
    19 extern "C" {
    20 #include <stdio.h>
    21 #include <string.h>
    22 #include <dlfcn.h>
    23 #include <unistd.h>
     12// Last Modified On : Sat May  5 11:37:35 2018
     13// Update Count     : 111
     14//
     15
     16#include <stdarg.h>                                                                             // va_start, va_end
     17#include <string.h>                                                                             // strlen
     18#include <unistd.h>                                                                             // _exit, getpid
    2419#define __USE_GNU
    2520#include <signal.h>
    2621#undef __USE_GNU
    27 #include <execinfo.h>
     22extern "C" {
     23#include <dlfcn.h>                                                                              // dlopen, dlsym
     24#include <execinfo.h>                                                                   // backtrace, messages
    2825}
    2926
    3027#include "bits/debug.h"
    3128#include "bits/defs.h"
    32 #include "bits/signal.h"
    33 #include "startup.h"
     29#include "bits/signal.h"                                                                // sigHandler_?
     30#include "startup.h"                                                                    // STARTUP_PRIORITY_CORE
    3431
    3532//=============================================================================================
     
    3734//=============================================================================================
    3835
    39 typedef void (*generic_fptr_t)(void);
    40 generic_fptr_t interpose_symbol( const char* symbol, const char *version ) {
     36typedef void (* generic_fptr_t)(void);
     37generic_fptr_t interpose_symbol( const char * symbol, const char * version ) {
    4138        const char * error;
    4239
     
    5552        } // if
    5653
    57         union { generic_fptr_t fptr; void* ptr; } originalFunc;
     54        union { generic_fptr_t fptr; void * ptr; } originalFunc;
    5855
    5956        #if defined( _GNU_SOURCE )
     
    7370}
    7471
    75 forall(dtype T)
    76 static inline void ptr_from_symbol( T** symbol_ptr, const char * symbol_name, const char * version) {
    77         union {
    78                 generic_fptr_t gp;
    79                 T* tp;
    80         } u;
    81 
    82         u.gp = interpose_symbol( symbol_name, version );
    83 
    84         *symbol_ptr = u.tp;
    85 }
    86 
    87 #define INTERPOSE_LIBC( x, ver ) ptr_from_symbol( (void**)&__cabi_libc.x, #x, ver)
    88 
    89 //=============================================================================================
    90 // Terminating Signals logic
     72#define INTERPOSE_LIBC( x, ver ) __cabi_libc.x = (typeof(__cabi_libc.x))interpose_symbol( #x, ver )
     73
     74//=============================================================================================
     75// Interposition Startup logic
    9176//=============================================================================================
    9277
     
    9883
    9984struct {
    100         void (* exit)( int ) __attribute__ (( __noreturn__ ));
    101         void (* abort)( void ) __attribute__ (( __noreturn__ ));
     85        void (* exit)( int ) __attribute__(( __noreturn__ ));
     86        void (* abort)( void ) __attribute__(( __noreturn__ ));
    10287} __cabi_libc;
    10388
     
    10792                const char *version = NULL;
    10893
     94#pragma GCC diagnostic push
     95#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
    10996                INTERPOSE_LIBC( abort, version );
    11097                INTERPOSE_LIBC( exit , version );
    111 
    112                 __cfaabi_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); // Failure handler
    113                 __cfaabi_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); // Failure handler
    114                 __cfaabi_sigaction( SIGILL , sigHandler_ill  , SA_SIGINFO ); // Failure handler
    115                 __cfaabi_sigaction( SIGFPE , sigHandler_fpe  , SA_SIGINFO ); // Failure handler
    116                 __cfaabi_sigaction( SIGABRT, sigHandler_abort, SA_SIGINFO ); // Failure handler
    117                 __cfaabi_sigaction( SIGTERM, sigHandler_term , SA_SIGINFO ); // Failure handler
    118                 __cfaabi_sigaction( SIGINT , sigHandler_term , SA_SIGINFO ); // Failure handler
     98#pragma GCC diagnostic pop
     99
     100                // Failure handler
     101                __cfaabi_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO );
     102                __cfaabi_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO );
     103                __cfaabi_sigaction( SIGILL , sigHandler_ill  , SA_SIGINFO );
     104                __cfaabi_sigaction( SIGFPE , sigHandler_fpe  , SA_SIGINFO );
     105                __cfaabi_sigaction( SIGABRT, sigHandler_abort, SA_SIGINFO | SA_RESETHAND);
     106                __cfaabi_sigaction( SIGTERM, sigHandler_term , SA_SIGINFO );
     107                __cfaabi_sigaction( SIGINT , sigHandler_term , SA_SIGINFO );
    119108        }
    120109}
     
    125114
    126115// Forward declare abort after the __typeof__ call to avoid ambiguities
    127 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    128 void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     116void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
     117void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
    129118
    130119extern "C" {
    131         void abort( void ) __attribute__ (( __nothrow__, __leaf__, __noreturn__ )) {
     120        void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
    132121                abort( NULL );
    133122        }
    134123
    135         void __cabi_abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
     124        void __cabi_abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
    136125                va_list argp;
    137126                va_start( argp, fmt );
     
    140129        }
    141130
    142         void exit( int status ) __attribute__ (( __nothrow__, __leaf__, __noreturn__ )) {
     131        void exit( int status ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
    143132                __cabi_libc.exit( status );
    144133        }
    145134}
    146135
    147 void * kernel_abort    ( void ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) { return NULL; }
    148 void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) {}
    149 int kernel_abort_lastframe( void ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) { return 4; }
     136void * kernel_abort    ( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return NULL; }
     137void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}
     138int kernel_abort_lastframe( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 4; }
    150139
    151140enum { abort_text_size = 1024 };
     
    153142static int abort_lastframe;
    154143
    155 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) {
     144void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) {
    156145    va_list args;
    157146    va_start( args, fmt );
     
    161150}
    162151
    163 void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
     152void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
    164153        void * kernel_data = kernel_abort();                    // must be done here to lock down kernel
    165154        int len;
  • src/libcfa/stdlib

    r7d0a3ba r358cba0  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jan  2 12:21:04 2018
    13 // Update Count     : 292
     12// Last Modified On : Sun May 13 23:22:23 2018
     13// Update Count     : 299
    1414//
    1515
    1616#pragma once
    1717
    18 //#define _XOPEN_SOURCE 600                                                             // posix_memalign, *rand48
     18#define __USE_ISOC11                                                                    // aligned_alloc
    1919#include <stdlib.h>                                                                             // strto*, *abs
    2020
     
    2828//---------------------------------------
    2929
    30 // allocation, non-array types
    31 static inline forall( dtype T | sized(T) ) T * malloc( void ) {
    32         // printf( "* malloc\n" );
    33         return (T *)(void *)malloc( (size_t)sizeof(T) );        // C malloc
    34 } // malloc
    35 
    36 // static inline forall( dtype T | sized(T) ) T & malloc( void ) {
    37 //      int & p = *(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    38 //      printf( "& malloc %p\n", &p );
    39 //      return p;
    40 // //   return (T &)*(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    41 // } // malloc
    42 
    43 extern "C" { void * calloc( size_t dim, size_t size ); } // default C routine
    44 static inline forall( dtype T | sized(T) ) T * calloc( size_t dim ) {
    45         //printf( "X2\n" );
    46         return (T *)(void *)calloc( dim, sizeof(T) );           // C cmalloc
    47 }
    48 
    49 extern "C" { void * realloc( void * ptr, size_t size ); } // default C routine for void *
    50 static inline forall( dtype T | sized(T) ) T * realloc( T * ptr, size_t size ) {
    51         //printf( "X3\n" );
    52         return (T *)(void *)realloc( (void *)ptr, size );
    53 }
    54 
    55 extern "C" { void * memalign( size_t align, size_t size ); } // use default C routine for void *
    56 static inline forall( dtype T | sized(T) ) T * memalign( size_t align ) {
    57         //printf( "X4\n" );
    58         return (T *)memalign( align, sizeof(T) );
    59 } // memalign
    60 
    61 static inline forall( dtype T | sized(T) ) T * aligned_alloc( size_t align ) {
    62         //printf( "X5\n" );
    63         return (T *)memalign( align, sizeof(T) );
    64 } // aligned_alloc
    65 
    66 extern "C" { int posix_memalign( void ** ptr, size_t align, size_t size ); } // use default C routine for void *
    67 static inline forall( dtype T | sized(T) ) int posix_memalign( T ** ptr, size_t align ) {
    68         //printf( "X6\n" );
    69         return posix_memalign( (void **)ptr, align, sizeof(T) );
    70 } // posix_memalign
    71 
    72 
    73 extern "C" { void * memset( void * dest, int c, size_t size ); } // use default C routine for void *
    74 
    75 static inline forall( dtype T | sized(T) ) T * alloc( void ) {
    76         //printf( "X7\n" );
    77         return (T *)(void *)malloc( (size_t)sizeof(T) );        // C malloc
    78 } // alloc
    79 static inline forall( dtype T | sized(T) ) T * alloc( char fill ) {
    80         //printf( "X8\n" );
    81         T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) );     // C malloc
    82     return (T *)memset( ptr, (int)fill, sizeof(T) );    // initial with fill value
    83 } // alloc
    84 
    85 static inline forall( dtype T | sized(T) ) T * alloc( size_t dim ) {
    86         //printf( "X9\n" );
    87         return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
    88 } // alloc
    89 static inline forall( dtype T | sized(T) ) T * alloc( size_t dim, char fill ) {
    90         //printf( "X10\n" );
    91         T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
    92     return (T *)memset( ptr, (int)fill, dim * sizeof(T) );
    93 } // alloc
    94 
    95 static inline forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim ) {
    96         //printf( "X11\n" );
    97         return (T *)(void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc
    98 } // alloc
     30// C dynamic allocation
     31static inline forall( dtype T | sized(T) ) {
     32        T * malloc( void ) {
     33                // printf( "* malloc\n" );
     34                return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     35        } // malloc
     36
     37        // T & malloc( void ) {
     38        //      int & p = *(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     39        //      printf( "& malloc %p\n", &p );
     40        //      return p;
     41        //      //      return (T &)*(T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     42        // } // malloc
     43
     44        T * calloc( size_t dim ) {
     45                //printf( "X2\n" );
     46                return (T *)(void *)calloc( dim, sizeof(T) );   // C calloc
     47        } // calloc
     48
     49        T * realloc( T * ptr, size_t size ) {
     50                //printf( "X3\n" );
     51                return (T *)(void *)realloc( (void *)ptr, size );
     52        } // realloc
     53
     54        extern "C" { void * memalign( size_t align, size_t size ); } // use default C routine for void *
     55        T * memalign( size_t align ) {
     56                //printf( "X4\n" );
     57                return (T *)memalign( align, sizeof(T) );
     58        } // memalign
     59
     60        extern "C" { void * aligned_alloc( size_t align, size_t size ); } // use default C routine for void *
     61        T * aligned_alloc( size_t align ) {
     62                //printf( "X5\n" );
     63                return (T *)aligned_alloc( align, sizeof(T) );
     64        } // aligned_alloc
     65
     66        int posix_memalign( T ** ptr, size_t align ) {
     67                //printf( "X6\n" );
     68                return posix_memalign( (void **)ptr, align, sizeof(T) ); // C posix_memalign
     69        } // posix_memalign
     70
     71
     72        // Cforall dynamic allocation
     73        extern "C" { void * memset( void * dest, int c, size_t size ); } // use default C routine for void *
     74
     75        T * alloc( void ) {
     76                //printf( "X7\n" );
     77                return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
     78        } // alloc
     79
     80        T * alloc( char fill ) {
     81                //printf( "X8\n" );
     82                T * ptr = (T *)(void *)malloc( (size_t)sizeof(T) );     // C malloc
     83                return (T *)memset( ptr, (int)fill, sizeof(T) );        // initial with fill value
     84        } // alloc
     85
     86        T * alloc( size_t dim ) {
     87                //printf( "X9\n" );
     88                return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
     89        } // alloc
     90
     91        T * alloc( size_t dim, char fill ) {
     92                //printf( "X10\n" );
     93                T * ptr = (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
     94                return (T *)memset( ptr, (int)fill, dim * sizeof(T) );    // initial with fill value
     95        } // alloc
     96
     97        T * alloc( T ptr[], size_t dim ) {
     98                //printf( "X11\n" );
     99                return (T *)(void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc
     100        } // alloc
     101} // distribution
     102
     103
    99104forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
    100105
  • src/libcfa/time.c

    r7d0a3ba r358cba0  
    1010// Created On       : Tue Mar 27 13:33:14 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Apr 12 14:41:00 2018
    13 // Update Count     : 22
     12// Last Modified On : Sun May  6 22:26:00 2018
     13// Update Count     : 37
    1414//
    1515
     
    1717#include "iostream"
    1818#include <stdio.h>                                                                              // snprintf
     19#include <assert.h>
    1920
    2021static char * nanomsd( long int ns, char * buf ) {              // most significant digits
     
    8788        time_t s = tv / TIMEGRAN;
    8889        tm tm;
    89         gmtime_r( &s, &tm );
     90        gmtime_r( &s, &tm );                                                            // tm_mon <= 11, tm_mday <= 31
     91#if defined(__GNUC__) && __GNUC__ >= 7
     92#pragma GCC diagnostic push
     93#pragma GCC diagnostic ignored "-Wformat-truncation"
     94#endif
    9095        snprintf( buf, 9, "%02d/%02d/%02d", tm.tm_year % 99, tm.tm_mon + 1, tm.tm_mday );
     96#if defined(__GNUC__) && __GNUC__ >= 7
     97#pragma GCC diagnostic pop
     98#endif
    9199        return buf;
    92100} // yy_mm_dd
     
    95103        time_t s = tv / TIMEGRAN;
    96104        tm tm;
    97         gmtime_r( &s, &tm );
     105        gmtime_r( &s, &tm );                                                            // tm_mon <= 11, tm_mday <= 31
     106#if defined(__GNUC__) && __GNUC__ >= 7
     107#pragma GCC diagnostic push
     108#pragma GCC diagnostic ignored "-Wformat-truncation"
     109#endif
    98110        snprintf( buf, 9, "%02d/%02d/%02d", tm.tm_mon + 1, tm.tm_mday, tm.tm_year % 99 );
     111#if defined(__GNUC__) && __GNUC__ >= 7
     112#pragma GCC diagnostic pop
     113#endif
    99114        return buf;
    100115} // mm_dd_yy
     
    103118        time_t s = tv / TIMEGRAN;
    104119        tm tm;
    105         gmtime_r( &s, &tm );
     120        gmtime_r( &s, &tm );                                                            // tm_mon <= 11, tm_mday <= 31
     121#if defined(__GNUC__) && __GNUC__ >= 7
     122#pragma GCC diagnostic push
     123#pragma GCC diagnostic ignored "-Wformat-truncation"
     124#endif
    106125        snprintf( buf, 9, "%02d/%02d/%02d", tm.tm_mday, tm.tm_mon + 1, tm.tm_year % 99 );
     126#if defined(__GNUC__) && __GNUC__ >= 7
     127#pragma GCC diagnostic pop
     128#endif
    107129        return buf;
    108130} // dd_mm_yy
  • src/main.cc

    r7d0a3ba r358cba0  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May  2 14:59:02 2018
    13 // Update Count     : 490
     12// Last Modified On : Mon May  7 14:35:57 2018
     13// Update Count     : 492
    1414//
    1515
     
    6464
    6565#define PASS(name, pass)                   \
    66         if ( errorp ) { cerr << #name << endl; } \
    67         HeapStats::newPass(#name);               \
     66        if ( errorp ) { cerr << name << endl; } \
     67        HeapStats::newPass(name);               \
    6868        pass;
    6969
     
    371371                } // if
    372372                return 1;
    373         } // try
     373        } catch(...) {
     374                std::exception_ptr eptr = std::current_exception();
     375                try {
     376                        if (eptr) {
     377                                std::rethrow_exception(eptr);
     378                        }
     379                        else {
     380                                std::cerr << "Exception Uncaught and Unkown" << std::endl;
     381                        }
     382                } catch(const std::exception& e) {
     383                        std::cerr << "Unaught Exception \"" << e.what() << "\"\n";
     384                }
     385                return 1;
     386        }// try
    374387
    375388        deleteAll( translationUnit );
    376         HeapStats::printStats();
     389        if(!libcfap && !treep) HeapStats::printStats();
    377390        return 0;
    378391} // main
     
    407420        opterr = 0;                                                                                     // (global) prevent getopt from printing error messages
    408421
    409         bool Werror = false;
     422        bool Wsuppress = false, Werror = false;
    410423        int c;
    411424        while ( (c = getopt_long( argc, argv, "abBcCdefgGlLmnNpqrstTvwW:yzZD:F:", long_opts, &long_index )) != -1 ) {
     
    495508                        break;
    496509                  case 'w':
    497                         SemanticWarning_SuppressAll();
     510                        Wsuppress = true;
    498511                        break;
    499512                  case 'W':
     
    534547                                assertf( false, "Unknown option: %s\n", argv[optind - 1] );
    535548                        } // if
    536                         #if __GNUC__ < 7
    537                         #else
     549                        #if defined(__GNUC__) && __GNUC__ >= 7
    538550                                __attribute__((fallthrough));
    539551                        #endif
     
    545557        if ( Werror ) {
    546558                SemanticWarning_WarningAsError();
     559        } // if
     560        if ( Wsuppress ) {
     561                SemanticWarning_SuppressAll();
    547562        } // if
    548563        // for ( const auto w : WarningFormats ) {
  • src/tests/coroutine/fmtLines.c

    r7d0a3ba r358cba0  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // fmtLines.cc --
     7// fmtLines.cc -- format characters into blocks of 4 and groups of 5 blocks per line
    88//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sun Sep 17 21:56:15 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Dec  5 21:56:35 2017
    13 // Update Count     : 38
     12// Last Modified On : Tue May 15 12:25:33 2018
     13// Update Count     : 42
    1414//
    1515
     
    2121        int g, b;                                                                                       // global because used in destructor
    2222};
    23 
    24 void ?{}( Format & fmt ) {
    25         resume( fmt );                                                                          // prime (start) coroutine
    26 }
    27 
    28 void ^?{}( Format & fmt ) with( fmt ) {
    29         if ( g != 0 || b != 0 ) sout | endl;
    30 }
    3123
    3224void main( Format & fmt ) with( fmt ) {
     
    4638} // main
    4739
    48 void prt( Format & fmt, char ch ) {
    49         fmt.ch = ch;
     40void ?{}( Format & fmt ) {
     41        resume( fmt );                                                                          // prime (start) coroutine
     42}
     43
     44void ^?{}( Format & fmt ) with( fmt ) {
     45        if ( g != 0 || b != 0 ) sout | endl;
     46}
     47
     48void format( Format & fmt ) {
    5049        resume( fmt );
    5150} // prt
    5251
    5352int main() {
    54         Format fmt;                                                                                     // format characters into blocks of 4 and groups of 5 blocks per line
    55         char ch;
     53        Format fmt;
    5654
    57         Eof: for ( ;; ) {                                                                       // read until end of file
    58                 sin | ch;                                                                               // read one character
    59           if ( eof( sin ) ) break Eof;                                          // eof ?
    60                 prt( fmt, ch );                                                                 // push character for formatting
     55        eof: for ( ;; ) {                                                                       // read until end of file
     56                sin | fmt.ch;                                                                   // read one character
     57          if ( eof( sin ) ) break eof;                                          // eof ?
     58                format( fmt );                                                                  // push character for formatting
    6159        } // for
    6260} // main
Note: See TracChangeset for help on using the changeset viewer.