Changes in / [d56ca354:c40e7c5]


Ignore:
Files:
3 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • doc/papers/general/Makefile

    rd56ca354 rc40e7c5  
    1818
    1919FIGURES = ${addsuffix .tex, \
    20 Cdecl \
    2120}
    2221
  • doc/papers/general/Paper.tex

    rd56ca354 rc40e7c5  
    22
    33\usepackage{fullpage}
    4 \usepackage{epic,eepic}
    54\usepackage{xspace,calc,comment}
    65\usepackage{upquote}                                                                    % switch curled `'" to straight
     
    3736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    3837
    39 \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
     38\newcommand{\Textbf}[1]{{\color{red}\textbf{#1}}}
    4039\newcommand{\TODO}[1]{\textbf{TODO}: {\itshape #1}} % TODO included
    4140%\newcommand{\TODO}[1]{} % TODO elided
     
    102101\makeatother
    103102
    104 \newenvironment{cquote}{%
    105         \list{}{\lstset{resetmargins=true,aboveskip=0pt,belowskip=0pt}\topsep=4pt\parsep=0pt\leftmargin=\parindent\rightmargin\leftmargin}%
    106         \item\relax
    107 }{%
    108         \endlist
    109 }% cquote
    110 
    111103% CFA programming language, based on ANSI C (with some gcc additions)
    112104\lstdefinelanguage{CFA}[ANSI]{C}{
     
    234226int forty_two = identity( 42 );                         $\C{// T is bound to int, forty\_two == 42}$
    235227\end{lstlisting}
    236 The @identity@ function above can be applied to any complete \newterm{object type} (or @otype@).
     228The @identity@ function above can be applied to any complete \emph{object type} (or @otype@).
    237229The type variable @T@ is transformed into a set of additional implicit parameters encoding sufficient information about @T@ to create and return a variable of that type.
    238230The \CFA implementation passes the size and alignment of the type represented by an @otype@ parameter, as well as an assignment operator, constructor, copy constructor and destructor.
    239 If this extra information is not needed, \eg for a pointer, the type parameter can be declared as a \newterm{data type} (or @dtype@).
     231If this extra information is not needed, \eg for a pointer, the type parameter can be declared as a \emph{data type} (or @dtype@).
    240232
    241233In \CFA, the polymorphism runtime-cost is spread over each polymorphic call, due to passing more arguments to polymorphic functions;
     
    243235A design advantage is that, unlike \CC template-functions, \CFA polymorphic-functions are compatible with C \emph{separate compilation}, preventing compilation and code bloat.
    244236
    245 Since bare polymorphic-types provide a restricted set of available operations, \CFA provides a \newterm{type assertion}~\cite[pp.~37-44]{Alphard} mechanism to provide further type information, where type assertions may be variable or function declarations that depend on a polymorphic type-variable.
     237Since bare polymorphic-types provide a restricted set of available operations, \CFA provides a \emph{type assertion}~\cite[pp.~37-44]{Alphard} mechanism to provide further type information, where type assertions may be variable or function declarations that depend on a polymorphic type-variable.
    246238For example, the function @twice@ can be defined using the \CFA syntax for operator overloading:
    247239\begin{lstlisting}
     
    310302\end{lstlisting}
    311303Here, the single name @MAX@ replaces all the C type-specific names: @SHRT_MAX@, @INT_MAX@, @DBL_MAX@.
     304As well, restricted constant overloading is allowed for the values @0@ and @1@, which have special status in C, \eg the value @0@ is both an integer and a pointer literal, so its meaning depends on context.
     305In addition, several operations are defined in terms values @0@ and @1@, \eg:
     306\begin{lstlisting}
     307int x;
     308if (x) x++                                                                      $\C{// if (x != 0) x += 1;}$
     309\end{lstlisting}
     310Every @if@ and iteration statement in C compares the condition with @0@, and every increment and decrement operator is semantically equivalent to adding or subtracting the value @1@ and storing the result.
     311Due to these rewrite rules, the values @0@ and @1@ have the types @zero_t@ and @one_t@ in \CFA, which allows overloading various operations for new types that seamlessly connect to all special @0@ and @1@ contexts.
     312The types @zero_t@ and @one_t@ have special built in implicit conversions to the various integral types, and a conversion to pointer types for @0@, which allows standard C code involving @0@ and @1@ to work as normal.
     313
    312314
    313315\subsection{Traits}
    314316
    315 \CFA provides \newterm{traits} to name a group of type assertions, where the trait name allows specifying the same set of assertions in multiple locations, preventing repetition mistakes at each function declaration:
     317\CFA provides \emph{traits} to name a group of type assertions, where the trait name allows specifying the same set of assertions in multiple locations, preventing repetition mistakes at each function declaration:
    316318\begin{lstlisting}
    317319trait summable( otype T ) {
     
    337339Given the information provided for an @otype@, variables of polymorphic type can be treated as if they were a complete type: stack-allocatable, default or copy-initialized, assigned, and deleted.
    338340
    339 In summation, the \CFA type-system uses \newterm{nominal typing} for concrete types, matching with the C type-system, and \newterm{structural typing} for polymorphic types.
     341In summation, the \CFA type-system uses \emph{nominal typing} for concrete types, matching with the C type-system, and \emph{structural typing} for polymorphic types.
    340342Hence, trait names play no part in type equivalence;
    341343the names are simply macros for a list of polymorphic assertions, which are expanded at usage sites.
     
    382384Furthermore, writing and using preprocessor macros can be unnatural and inflexible.
    383385
    384 \CC, Java, and other languages use \newterm{generic types} to produce type-safe abstract data-types.
     386\CC, Java, and other languages use \emph{generic types} to produce type-safe abstract data-types.
    385387\CFA also implements generic types that integrate efficiently and naturally with the existing polymorphic functions, while retaining backwards compatibility with C and providing separate compilation.
    386388However, for known concrete parameters, the generic-type definition can be inlined, like \CC templates.
     
    403405\end{lstlisting}
    404406
    405 \CFA classifies generic types as either \newterm{concrete} or \newterm{dynamic}.
     407\CFA classifies generic types as either \emph{concrete} or \emph{dynamic}.
    406408Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters.
    407 A type may have polymorphic parameters but still be concrete, called \newterm{dtype-static}.
     409A type may have polymorphic parameters but still be concrete, called \emph{dtype-static}.
    408410Polymorphic 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.
    409411
     
    442444Though \CFA implements concrete generic-types efficiently, it also has a fully general system for dynamic generic types.
    443445As mentioned in Section~\ref{sec:poly-fns}, @otype@ function parameters (in fact all @sized@ polymorphic parameters) come with implicit size and alignment parameters provided by the caller.
    444 Dynamic generic-types also have an \newterm{offset array} containing structure-member offsets.
     446Dynamic generic-types also have an \emph{offset array} containing structure-member offsets.
    445447A dynamic generic-union needs no such offset array, as all members are at offset 0, but size and alignment are still necessary.
    446448Access to members of a dynamic structure is provided at runtime via base-displacement addressing with the structure pointer and the member offset (similar to the @offsetof@ macro), moving a compile-time offset calculation to runtime.
     
    455457For instance, modularity is generally provided in C by including an opaque forward-declaration of a structure and associated accessor and mutator functions in a header file, with the actual implementations in a separately-compiled @.c@ file.
    456458\CFA supports this pattern for generic types, but the caller does not know the actual layout or size of the dynamic generic-type, and only holds it by a pointer.
    457 The \CFA translator automatically generates \newterm{layout functions} for cases where the size, alignment, and offset array of a generic struct cannot be passed into a function from that function's caller.
     459The \CFA translator automatically generates \emph{layout functions} for cases where the size, alignment, and offset array of a generic struct cannot be passed into a function from that function's caller.
    458460These layout functions take as arguments pointers to size and alignment variables and a caller-allocated array of member offsets, as well as the size and alignment of all @sized@ parameters to the generic structure (un@sized@ parameters are forbidden from being used in a context that affects layout).
    459461Results of these layout functions are cached so that they are only computed once per type per function. %, as in the example below for @pair@.
     
    479481Since @pair(T *, T * )@ is a concrete type, there are no implicit parameters passed to @lexcmp@, so the generated code is identical to a function written in standard C using @void *@, yet the \CFA version is type-checked to ensure the fields of both pairs and the arguments to the comparison function match in type.
    480482
    481 Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \newterm{tag-structures}.
     483Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \emph{tag-structures}.
    482484Sometimes information is only used for type-checking and can be omitted at runtime, \eg:
    483485\begin{lstlisting}
     
    535537The addition of multiple-return-value functions (MRVF) are useless without a syntax for accepting multiple values at the call-site.
    536538The simplest mechanism for capturing the return values is variable assignment, allowing the values to be retrieved directly.
    537 As such, \CFA allows assigning multiple values from a function into multiple variables, using a square-bracketed list of lvalue expressions (as above), called a \newterm{tuple}.
    538 
    539 However, functions also use \newterm{composition} (nested calls), with the direct consequence that MRVFs must also support composition to be orthogonal with single-returning-value functions (SRVF), \eg:
     539As such, \CFA allows assigning multiple values from a function into multiple variables, using a square-bracketed list of lvalue expressions (as above), called a \emph{tuple}.
     540
     541However, functions also use \emph{composition} (nested calls), with the direct consequence that MRVFs must also support composition to be orthogonal with single-returning-value functions (SRVF), \eg:
    540542\begin{lstlisting}
    541543printf( "%d %d\n", div( 13, 5 ) );                      $\C{// return values seperated into arguments}$
     
    570572printf( "%d %d\n", qr );
    571573\end{lstlisting}
    572 \CFA also supports \newterm{tuple indexing} to access single components of a tuple expression:
     574\CFA also supports \emph{tuple indexing} to access single components of a tuple expression:
    573575\begin{lstlisting}
    574576[int, int] * p = &qr;                                           $\C{// tuple pointer}$
     
    613615\subsection{Tuple Assignment}
    614616
    615 An assignment where the left side is a tuple type is called \newterm{tuple assignment}.
    616 There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a tuple type or a non-tuple type, called \newterm{multiple} and \newterm{mass assignment}, respectively.
     617An assignment where the left side is a tuple type is called \emph{tuple assignment}.
     618There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a tuple type or a non-tuple type, called \emph{multiple} and \emph{mass assignment}, respectively.
    617619%\lstDeleteShortInline@%
    618620%\par\smallskip
     
    648650\subsection{Member Access}
    649651
    650 It is also possible to access multiple fields from a single expression using a \newterm{member-access}.
     652It is also possible to access multiple fields from a single expression using a \emph{member-access}.
    651653The result is a single tuple-valued expression whose type is the tuple of the types of the members, \eg:
    652654\begin{lstlisting}
     
    778780Matching against a @ttype@ parameter consumes all remaining argument components and packages them into a tuple, binding to the resulting tuple of types.
    779781In a given parameter list, there must be at most one @ttype@ parameter that occurs last, which matches normal variadic semantics, with a strong feeling of similarity to \CCeleven variadic templates.
    780 As such, @ttype@ variables are also called \newterm{argument packs}.
     782As such, @ttype@ variables are also called \emph{argument packs}.
    781783
    782784Like variadic templates, the main way to manipulate @ttype@ polymorphic functions is via recursion.
     
    850852\subsection{Implementation}
    851853
    852 Tuples are implemented in the \CFA translator via a transformation into \newterm{generic types}.
     854Tuples are implemented in the \CFA translator via a transformation into \emph{generic types}.
    853855For each $N$, the first time an $N$-tuple is seen in a scope a generic type with $N$ type parameters is generated, \eg:
    854856\begin{lstlisting}
     
    901903Similarly, tuple member expressions are recursively expanded into a list of member access expressions.
    902904
    903 Expressions that may contain side effects are made into \newterm{unique expressions} before being expanded by the flattening conversion.
     905Expressions that may contain side effects are made into \emph{unique expressions} before being expanded by the flattening conversion.
    904906Each unique expression is assigned an identifier and is guaranteed to be executed exactly once:
    905907\begin{lstlisting}
     
    10501052\label{s:WithClauseStatement}
    10511053
    1052 Grouping heterogenous data into \newterm{aggregate}s (structure/union) is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers:
     1054Grouping heterogenous data into \newterm{aggregate}s is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers:
    10531055\begin{cfa}
    1054 struct S {                                                                      $\C{// aggregate}$
    1055         char c;                                                                 $\C{// fields}$
     1056struct S {                                                              $\C{// aggregate}$
     1057        char c;                                                         $\C{// fields}$
    10561058        int i;
    10571059        double d;
     
    10591061S s, as[10];
    10601062\end{cfa}
    1061 However, routines manipulating aggregates must repeat the aggregate name to access its containing fields:
     1063However, routines manipulating aggregates have repeition of the aggregate name to access its containing fields:
    10621064\begin{cfa}
    10631065void f( S s ) {
    1064         `s.`c; `s.`i; `s.`d;                                    $\C{// access containing fields}$
     1066        `s.`c; `s.`i; `s.`d;                            $\C{// access containing fields}$
    10651067}
    10661068\end{cfa}
     
    10681070\begin{C++}
    10691071class C {
    1070         char c;                                                                 $\C{// fields}$
     1072        char c;                                                         $\C{// fields}$
    10711073        int i;
    10721074        double d;
    1073         int mem() {                                                             $\C{// implicit "this" parameter}$
    1074                 `this->`c; `this->`i; `this->`d;        $\C{// access containing fields}$
     1075        int mem() {                                                     $\C{// implicit "this" parameter}$
     1076                `this->`c; `this->`i; `this->`d;$\C{// access containing fields}$
    10751077        }
    10761078}
    10771079\end{C++}
    1078 Nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.
    1079 However, for other aggregate parameters, qualification is necessary:
    1080 \begin{cfa}
    1081 struct T { double m, n; };
    1082 int C::mem( T & t ) {                                           $\C{// multiple aggregate parameters}$
    1083         c; i; d;                                                                $\C{\color{red}// this-\textgreater.c, this-\textgreater.i, this-\textgreater.d}$
    1084         `t.`m; `t.`n;                                                   $\C{// must qualify}$
    1085 }
    1086 \end{cfa}
     1080Nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of nested lexical-scoping.
    10871081
    10881082% In object-oriented programming, there is an implicit first parameter, often names @self@ or @this@, which is elided.
    10891083% In any programming language, some functions have a naturally close relationship with a particular data type.
    1090 % Object-oriented programming allows this close relationship to be codified in the language by making such functions \newterm{class methods} of their related data type.
     1084% Object-oriented programming allows this close relationship to be codified in the language by making such functions \emph{class methods} of their related data type.
    10911085% Class methods have certain privileges with respect to their associated data type, notably un-prefixed access to the fields of that data type.
    10921086% When writing C functions in an object-oriented style, this un-prefixed access is swiftly missed, as access to fields of a @Foo* f@ requires an extra three characters @f->@ every time, which disrupts coding flow and clutters the produced code.
     
    10941088% \TODO{Fill out section. Be sure to mention arbitrary expressions in with-blocks, recent change driven by Thierry to prioritize field name over parameters.}
    10951089
    1096 To simplify the programmer experience, \CFA provides a @with@ clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing the field identifiers.
    1097 Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block.
     1090\CFA provides a @with@ clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing field identifiers.
     1091Hence, the qualified fields become variables, and making it easier to optimize field references in a block.
    10981092\begin{cfa}
    1099 void f( S s ) `with( s )` {                                     $\C{// with clause}$
    1100         c; i; d;                                                                $\C{\color{red}// s.c, s.i, s.d}$
     1093void f( S s ) `with( s )` {                             $\C{// with clause}$
     1094        c; i; d;                                                        $\C{\color{red}// s.c, s.i, s.d}$
    11011095}
    11021096\end{cfa}
     
    11041098\begin{cfa}
    11051099int mem( S & this ) `with( this )` {            $\C{// with clause}$
    1106         c; i; d;                                                                $\C{\color{red}// this.c, this.i, this.d}$
     1100        c; i; d;                                                        $\C{\color{red}// this.c, this.i, this.d}$
    11071101}
    11081102\end{cfa}
    1109 with the generality of opening multiple aggregate-parameters:
     1103The key generality over the object-oriented approach is that one aggregate parameter \lstinline[language=C++]@this@ is not treated specially over other aggregate parameters:
    11101104\begin{cfa}
     1105struct T { double m, n; };
    11111106int mem( S & s, T & t ) `with( s, t )` {        $\C{// multiple aggregate parameters}$
    1112         c; i; d;                                                                $\C{\color{red}// s.c, s.i, s.d}$
    1113         m; n;                                                                   $\C{\color{red}// t.m, t.n}$
     1107        c; i; d;                                                        $\C{\color{red}// s.c, s.i, s.d}$
     1108        m; n;                                                           $\C{\color{red}// t.m, t.n}$
    11141109}
    11151110\end{cfa}
    1116 
    1117 In detail, the @with@ clause/statement has the form:
     1111The equivalent object-oriented style is:
    11181112\begin{cfa}
    1119 $\emph{with-statement}$:
    1120         'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$
    1121 \end{cfa}
    1122 and may appear as the body of a routine or nested within a routine body.
    1123 Each expression in the expression-list provides a type and object.
    1124 The type must be an aggregate type.
    1125 (Enumerations are already opened.)
    1126 The object is the implicit qualifier for the open structure-fields.
    1127 
    1128 All expressions in the expression list are open in ``parallel'' within the compound statement.
    1129 This semantic is different from Pascal, which nests the openings.
    1130 The difference between parallel and nesting occurs for fields with the same name but different type:
    1131 \begin{cfa}
    1132 struct S { int i; int j; double m; } s, w;
    1133 struct T { int i; int k; int m } t, w;
    1134 with( s, t ) {
    1135         j + k;                                                                  $\C{// unambiguous, s.j + t.m}$
    1136         m = 5.0;                                                                $\C{// unambiguous, t.m = 5.0}$
    1137         m = 1;                                                                  $\C{// unambiguous, s.m = 1}$
    1138         int a = s.i + m;                                                $\C{// unambiguous, a = s.i + t.i}$
    1139         int b = s.i + t.i;                                              $\C{// unambiguous, qualification}$
    1140         sout | (double)m | endl;                                $\C{// unambiguous, cast}$
    1141         i;                                                                              $\C{// ambiguous}$
    1142 }
    1143 \end{cfa}
    1144 \CFA's ability to overload variables means usages of field with the same names can be automatically disambiguated, eliminating most qualification.
    1145 Qualification or a cast is used to disambiguate.
    1146 A cast may be necessary to disambiguate between the overload variables in a @with@ expression:
    1147 \begin{cfa}
    1148 with( w ) { ... }                                                       $\C{// ambiguous, same name and no context}$
    1149 with( (S)w ) { ... }                                            $\C{// unambiguous}$
    1150 \end{cfa}
    1151 
    1152 \begin{cfa}
    1153 struct S { int i, j; } sv;
    1154 with( sv ) {
    1155         S & sr = sv;
    1156         with( sr ) {
    1157                 S * sp = &sv;
    1158                 with( *sp ) {
    1159                         i = 3; j = 4;                                   $\C{\color{red}// sp-{\textgreater}i, sp-{\textgreater}j}$
    1160                 }
    1161                 i = 3; j = 4;                                           $\C{\color{red}// sr.i, sr.j}$
    1162         }
    1163         i = 3; j = 4;                                                   $\C{\color{red}// sv.i, sv.j}$
     1113int S::mem( T & t ) {                                   $\C{// multiple aggregate parameters}$
     1114        c; i; d;                                                        $\C{\color{red}// this-\textgreater.c, this-\textgreater.i, this-\textgreater.d}$
     1115        `t.`m; `t.`n;
    11641116}
    11651117\end{cfa}
     
    11701122        struct S1 { ... } s1;
    11711123        struct S2 { ... } s2;
    1172         `with( s1 )` {                                                  $\C{// with statement}$
     1124        `with( s1 )` {                                          $\C{// with statement}$
    11731125                // access fields of s1 without qualification
    1174                 `with( s2 )` {                                          $\C{// nesting}$
     1126                `with( s2 )` {                                  $\C{// nesting}$
    11751127                        // access fields of s1 and s2 without qualification
    11761128                }
     
    11821134\end{cfa}
    11831135
     1136When opening multiple structures, fields with the same name and type are ambiguous and must be fully qualified.
     1137For fields with the same name but different type, context/cast can be used to disambiguate.
     1138\begin{cfa}
     1139struct S { int i; int j; double m; } a, c;
     1140struct T { int i; int k; int m } b, c;
     1141`with( a, b )` {
     1142        j + k;                                                  $\C{// unambiguous, unique names define unique types}$
     1143        i;                                                              $\C{// ambiguous, same name and type}$
     1144        a.i + b.i;                                              $\C{// unambiguous, qualification defines unique names}$
     1145        m;                                                              $\C{// ambiguous, same name and no context to define unique type}$
     1146        m = 5.0;                                                $\C{// unambiguous, same name and context defines unique type}$
     1147        m = 1;                                                  $\C{// unambiguous, same name and context defines unique type}$
     1148}
     1149`with( c )` { ... }                                     $\C{// ambiguous, same name and no context}$
     1150`with( (S)c )` { ... }                                  $\C{// unambiguous, same name and cast defines unique type}$
     1151\end{cfa}
     1152
     1153The components in the "with" clause
     1154
     1155  with ( a, b, c ) { ... }
     1156
     1157serve 2 purposes: each component provides a type and object. The type must be a
     1158structure type. Enumerations are already opened, and I think a union is opened
     1159to some extent, too. (Or is that just unnamed unions?) The object is the target
     1160that the naked structure-fields apply to. The components are open in "parallel"
     1161at the scope of the "with" clause/statement, so opening "a" does not affect
     1162opening "b", etc. This semantic is different from Pascal, which nests the
     1163openings.
     1164
     1165Having said the above, it seems reasonable to allow a "with" component to be an
     1166expression. The type is the static expression-type and the object is the result
     1167of the expression. Again, the type must be an aggregate. Expressions require
     1168parenthesis around the components.
     1169
     1170  with( a, b, c ) { ... }
     1171
     1172Does this now make sense?
     1173
     1174Having written more CFA code, it is becoming clear to me that I *really* want
     1175the "with" to be implemented because I hate having to type all those object
     1176names for fields. It's a great way to drive people away from the language.
     1177
    11841178
    11851179\subsection{Exception Handling ???}
     
    11961190\subsection{Alternative Declaration Syntax}
    11971191
    1198 \newcommand{\R}[1]{\Textbf{#1}}
    1199 \newcommand{\B}[1]{{\Textbf[blue]{#1}}}
    1200 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    1201 
    1202 C declaration syntax is notoriously confusing and error prone.
    1203 For example, many C programmers are confused by a declaration as simple as:
    1204 \begin{cquote}
    1205 \lstDeleteShortInline@%
    1206 \begin{tabular}{@{}ll@{}}
    1207 \begin{cfa}
    1208 int * x[5]
    1209 \end{cfa}
    1210 &
    1211 \raisebox{-0.75\totalheight}{\input{Cdecl}}
    1212 \end{tabular}
    1213 \lstMakeShortInline@%
    1214 \end{cquote}
    1215 Is this an array of 5 pointers to integers or a pointer to an array of 5 integers?
    1216 If there is any doubt, it implies productivity and safety issues even for basic programs.
    1217 Another example of confusion results from the fact that a routine name and its parameters are embedded within the return type, mimicking the way the return value is used at the routine's call site.
    1218 For example, a routine returning a pointer to an array of integers is defined and used in the following way:
    1219 \begin{cfa}
    1220 int `(*`f`())[`5`]` {...};                              $\C{// definition}$
    1221  ... `(*`f`())[`3`]` += 1;                              $\C{// usage}$
    1222 \end{cfa}
    1223 Essentially, the return type is wrapped around the routine name in successive layers (like an onion).
    1224 While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
    1225 
    1226 \CFA provides its own type, variable and routine declarations, using a different syntax.
    1227 The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right of the base type.
    1228 In the following example, \R{red} is the base type and \B{blue} is qualifiers.
    1229 The \CFA declarations move the qualifiers to the left of the base type, \ie move the blue to the left of the red, while the qualifiers have the same meaning but are ordered left to right to specify a variable's type.
    1230 \begin{cquote}
    1231 \lstDeleteShortInline@%
    1232 \lstset{moredelim=**[is][\color{blue}]{+}{+}}
    1233 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1234 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1235 \begin{cfa}
    1236 +[5] *+ `int` x1;
    1237 +* [5]+ `int` x2;
    1238 +[* [5] int]+ f`( int p )`;
    1239 \end{cfa}
    1240 &
    1241 \begin{cfa}
    1242 `int` +*+ x1 +[5]+;
    1243 `int` +(*+x2+)[5]+;
    1244 +int (*+f`( int p )`+)[5]+;
    1245 \end{cfa}
    1246 \end{tabular}
    1247 \lstMakeShortInline@%
    1248 \end{cquote}
    1249 The only exception is bit field specification, which always appear to the right of the base type.
    1250 % Specifically, the character @*@ is used to indicate a pointer, square brackets @[@\,@]@ are used to represent an array or function return value, and parentheses @()@ are used to indicate a routine parameter.
    1251 However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    1252 For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as follows:
    1253 \begin{cquote}
    1254 \lstDeleteShortInline@%
    1255 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1256 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1257 \begin{cfa}
    1258 `*` int x, y;
    1259 \end{cfa}
    1260 &
    1261 \begin{cfa}
    1262 int `*`x, `*`y;
    1263 \end{cfa}
    1264 \end{tabular}
    1265 \lstMakeShortInline@%
    1266 \end{cquote}
    1267 The downside of this semantics is the need to separate regular and pointer declarations:
    1268 \begin{cquote}
    1269 \lstDeleteShortInline@%
    1270 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1271 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1272 \begin{cfa}
    1273 `*` int x;
    1274 int y;
    1275 \end{cfa}
    1276 &
    1277 \begin{cfa}
    1278 int `*`x, y;
    1279 
    1280 \end{cfa}
    1281 \end{tabular}
    1282 \lstMakeShortInline@%
    1283 \end{cquote}
    1284 which is prescribing a safety benefit.
    1285 Other examples are:
    1286 \begin{cquote}
    1287 \lstDeleteShortInline@%
    1288 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    1289 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    1290 \begin{cfa}
    1291 [ 5 ] int z;
    1292 [ 5 ] * char w;
    1293 * [ 5 ] double v;
    1294 struct s {
    1295         int f0:3;
    1296         * int f1;
    1297         [ 5 ] * int f2;
    1298 };
    1299 \end{cfa}
    1300 &
    1301 \begin{cfa}
    1302 int z[ 5 ];
    1303 char * w[ 5 ];
    1304 double (* v)[ 5 ];
    1305 struct s {
    1306         int f0:3;
    1307         int * f1;
    1308         int * f2[ 5 ]
    1309 };
    1310 \end{cfa}
    1311 &
    1312 \begin{cfa}
    1313 // array of 5 integers
    1314 // array of 5 pointers to char
    1315 // pointer to array of 5 doubles
    1316 
    1317 // common bit field syntax
    1318 
    1319 
    1320 
    1321 \end{cfa}
    1322 \end{tabular}
    1323 \lstMakeShortInline@%
    1324 \end{cquote}
    1325 
    1326 All type qualifiers, \eg @const@, @volatile@, etc., are used in the normal way with the new declarations and also appear left to right, \eg:
    1327 \begin{cquote}
    1328 \lstDeleteShortInline@%
    1329 \begin{tabular}{@{}l@{\hspace{1em}}l@{\hspace{1em}}l@{}}
    1330 \multicolumn{1}{c@{\hspace{1em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{1em}}}{\textbf{C}} \\
    1331 \begin{cfa}
    1332 const * const int x;
    1333 const * [ 5 ] const int y;
    1334 \end{cfa}
    1335 &
    1336 \begin{cfa}
    1337 int const * const x;
    1338 const int (* const y)[ 5 ]
    1339 \end{cfa}
    1340 &
    1341 \begin{cfa}
    1342 // const pointer to const integer
    1343 // const pointer to array of 5 const integers
    1344 \end{cfa}
    1345 \end{tabular}
    1346 \lstMakeShortInline@%
    1347 \end{cquote}
    1348 All declaration qualifiers, \eg @extern@, @static@, etc., are used in the normal way with the new declarations but can only appear at the start of a \CFA routine declaration,\footnote{\label{StorageClassSpecifier}
    1349 The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}} \eg:
    1350 \begin{cquote}
    1351 \lstDeleteShortInline@%
    1352 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{2em}}l@{}}
    1353 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{C}} \\
    1354 \begin{cfa}
    1355 extern [ 5 ] int x;
    1356 static * const int y;
    1357 \end{cfa}
    1358 &
    1359 \begin{cfa}
    1360 int extern x[ 5 ];
    1361 const int static * y;
    1362 \end{cfa}
    1363 &
    1364 \begin{cfa}
    1365 // externally visible array of 5 integers
    1366 // internally visible pointer to constant int
    1367 \end{cfa}
    1368 \end{tabular}
    1369 \lstMakeShortInline@%
    1370 \end{cquote}
    1371 
    1372 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine @sizeof@:
    1373 \begin{cquote}
    1374 \lstDeleteShortInline@%
    1375 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1376 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1377 \begin{cfa}
    1378 y = (* int)x;
    1379 i = sizeof([ 5 ] * int);
    1380 \end{cfa}
    1381 &
    1382 \begin{cfa}
    1383 y = (int *)x;
    1384 i = sizeof(int * [ 5 ]);
    1385 \end{cfa}
    1386 \end{tabular}
    1387 \lstMakeShortInline@%
    1388 \end{cquote}
    1389 
    1390 Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
    1391 Therefore, a programmer has the option of either continuing to use traditional C declarations or take advantage of the new style.
    1392 Clearly, both styles need to be supported for some time due to existing C-style header-files, particularly for UNIX-like systems.
    1393 
    13941192
    13951193\subsection{References}
    13961194
    1397 All variables in C have an \newterm{address}, a \newterm{value}, and a \newterm{type};
    1398 at the position in the program's memory denoted by the address, there exists a sequence of bits (the value), with the length and semantic meaning of this bit sequence defined by the type.
    1399 The C type-system does not always track the relationship between a value and its address;
    1400 a value that does not have a corresponding address is called a \newterm{rvalue} (for ``right-hand value''), while a value that does have an address is called a \newterm{lvalue} (for ``left-hand value'').
    1401 For example, in @int x; x = 42;@ the variable expression @x@ on the left-hand-side of the assignment is a lvalue, while the constant expression @42@ on the right-hand-side of the assignment is a rvalue.
    1402 Despite the nomenclature of ``left-hand'' and ``right-hand'', an expression's classification as lvalue or rvalue is entirely dependent on whether it has an address or not; in imperative programming, the address of a value is used for both reading and writing (mutating) a value, and as such lvalues can be converted to rvalues and read from, but rvalues cannot be mutated because they lack a location to store the updated value.
    1403 
    1404 Within a lexical scope, lvalue expressions have an \newterm{address interpretation} for writing a value or a \newterm{value interpretation} to read a value.
    1405 For example, in @x = y@, @x@ has an address interpretation, while @y@ has a value interpretation.
    1406 Though this duality of interpretation is useful, C lacks a direct mechanism to pass lvalues between contexts, instead relying on \newterm{pointer types} to serve a similar purpose.
    1407 In C, for any type @T@ there is a pointer type @T *@, the value of which is the address of a value of type @T@.
    1408 A pointer rvalue can be explicitly \newterm{dereferenced} to the pointed-to lvalue with the dereference operator @*?@, while the rvalue representing the address of a lvalue can be obtained with the address-of operator @&?@.
     1195All variables in C have an \emph{address}, a \emph{value}, and a \emph{type}; at the position in the program's memory denoted by the address, there exists a sequence of bits (the value), with the length and semantic meaning of this bit sequence defined by the type.
     1196The C type system does not always track the relationship between a value and its address; a value that does not have a corresponding address is called a \emph{rvalue} (for ``right-hand value''), while a value that does have an address is called a \emph{lvalue} (for ``left-hand value''); in @int x; x = 42;@ the variable expression @x@ on the left-hand-side of the assignment is a lvalue, while the constant expression @42@ on the right-hand-side of the assignment is a rvalue.
     1197Which address a value is located at is sometimes significant; the imperative programming paradigm of C relies on the mutation of values at specific addresses.
     1198Within a lexical scope, lvalue exressions can be used in either their \emph{address interpretation} to determine where a mutated value should be stored or in their \emph{value interpretation} to refer to their stored value; in @x = y;@ in @{ int x, y = 7; x = y; }@, @x@ is used in its address interpretation, while y is used in its value interpretation.
     1199Though this duality of interpretation is useful, C lacks a direct mechanism to pass lvalues between contexts, instead relying on \emph{pointer types} to serve a similar purpose.
     1200In C, for any type @T@ there is a pointer type @T*@, the value of which is the address of a value of type @T@; a pointer rvalue can be explicitly \emph{dereferenced} to the pointed-to lvalue with the dereference operator @*?@, while the rvalue representing the address of a lvalue can be obtained with the address-of operator @&?@.
    14091201
    14101202\begin{cfa}
    14111203int x = 1, y = 2, * p1, * p2, ** p3;
    1412 p1 = &x;                                                                $\C{// p1 points to x}$
    1413 p2 = &y;                                                                $\C{// p2 points to y}$
    1414 p3 = &p1;                                                               $\C{// p3 points to p1}$
     1204p1 = &x;  $\C{// p1 points to x}$
     1205p2 = &y;  $\C{// p2 points to y}$
     1206p3 = &p1;  $\C{// p3 points to p1}$
    14151207*p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15);
    14161208\end{cfa}
     
    14181210Unfortunately, the dereference and address-of operators introduce a great deal of syntactic noise when dealing with pointed-to values rather than pointers, as well as the potential for subtle bugs.
    14191211For both brevity and clarity, it would be desirable to have the compiler figure out how to elide the dereference operators in a complex expression such as the assignment to @*p2@ above.
    1420 However, since C defines a number of forms of \newterm{pointer arithmetic}, two similar expressions involving pointers to arithmetic types (\eg @*p1 + x@ and @p1 + x@) may each have well-defined but distinct semantics, introducing the possibility that a user programmer may write one when they mean the other, and precluding any simple algorithm for elision of dereference operators.
     1212However, since C defines a number of forms of \emph{pointer arithmetic}, two similar expressions involving pointers to arithmetic types (\eg @*p1 + x@ and @p1 + x@) may each have well-defined but distinct semantics, introducing the possibility that a user programmer may write one when they mean the other, and precluding any simple algorithm for elision of dereference operators.
    14211213To solve these problems, \CFA introduces reference types @T&@; a @T&@ has exactly the same value as a @T*@, but where the @T*@ takes the address interpretation by default, a @T&@ takes the value interpretation by default, as below:
    14221214
    14231215\begin{cfa}
    1424 int x = 1, y = 2, & r1, & r2, && r3;
     1216inx x = 1, y = 2, & r1, & r2, && r3;
    14251217&r1 = &x;  $\C{// r1 points to x}$
    14261218&r2 = &y;  $\C{// r2 points to y}$
     
    14441236This allows \CFA references to be default-initialized (\eg to a null pointer), and also to point to different addresses throughout their lifetime.
    14451237This rebinding is accomplished without adding any new syntax to \CFA, but simply by extending the existing semantics of the address-of operator in C.
    1446 
    14471238In C, the address of a lvalue is always a rvalue, as in general that address is not stored anywhere in memory, and does not itself have an address.
    14481239In \CFA, the address of a @T&@ is a lvalue @T*@, as the address of the underlying @T@ is stored in the reference, and can thus be mutated there.
     
    14581249        if @L@ is an lvalue of type {@T &@$_1 \cdots$@ &@$_l$} where $l \ge 0$ references (@&@ symbols) then @&L@ has type {@T `*`&@$_{\color{red}1} \cdots$@ &@$_{\color{red}l}$}, \\ \ie @T@ pointer with $l$ references (@&@ symbols).
    14591250\end{itemize}
     1251
    14601252Since pointers and references share the same internal representation, code using either is equally performant; in fact the \CFA compiler converts references to pointers internally, and the choice between them in user code can be made based solely on convenience.
    1461 
    1462 By analogy to pointers, \CFA references also allow cv-qualifiers such as @const@:
     1253By analogy to pointers, \CFA references also allow cv-qualifiers:
    14631254
    14641255\begin{cfa}
     
    14781269
    14791270More generally, this initialization of references from lvalues rather than pointers is an instance of a ``lvalue-to-reference'' conversion rather than an elision of the address-of operator; this conversion can actually be used in any context in \CFA an implicit conversion would be allowed.
    1480 Similarly, use of a the value pointed to by a reference in an rvalue context can be thought of as a ``reference-to-rvalue'' conversion, and \CFA also includes a qualifier-adding ``reference-to-reference'' conversion, analogous to the @T *@ to @const T *@ conversion in standard C.
     1271Similarly, use of a the value pointed to by a reference in an rvalue context can be thought of as a ``reference-to-rvalue'' conversion, and \CFA also includes a qualifier-adding ``reference-to-reference'' conversion, analagous to the @T *@ to @const T *@ conversion in standard C.
    14811272The final reference conversion included in \CFA is ``rvalue-to-reference'' conversion, implemented by means of an implicit temporary.
    14821273When an rvalue is used to initialize a reference, it is instead used to initialize a hidden temporary value with the same lexical scope as the reference, and the reference is initialized to the address of this temporary.
    14831274This 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.
    1484 \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.
    1485 
     1275\CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \emph{const hell} problem, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.
    14861276
    14871277\subsection{Constructors and Destructors}
     
    14891279One of the strengths of C is the control over memory management it gives programmers, allowing resource release to be more consistent and precisely timed than is possible with garbage-collected memory management.
    14901280However, this manual approach to memory management is often verbose, and it is useful to manage resources other than memory (\eg file handles) using the same mechanism as memory.
    1491 \CC is well-known for an approach to manual memory management that addresses both these issues, Resource Aquisition Is Initialization (RAII), implemented by means of special \newterm{constructor} and \newterm{destructor} functions; we have implemented a similar feature in \CFA.
     1281\CC is well-known for an approach to manual memory management that addresses both these issues, Resource Aquisition Is Initialization (RAII), implemented by means of special \emph{constructor} and \emph{destructor} functions; we have implemented a similar feature in \CFA.
    14921282While RAII is a common feature of object-oriented programming languages, its inclusion in \CFA does not violate the design principle that \CFA retain the same procedural paradigm as C.
    14931283In particular, \CFA does not implement class-based encapsulation: neither the constructor nor any other function has privileged access to the implementation details of a type, except through the translation-unit-scope method of opaque structs provided by C.
     
    15211311\end{cfa}
    15221312
    1523 In the example above, a \newterm{default constructor} (\ie one with no parameters besides the @this@ parameter) and destructor are defined for the @Array@ struct, a dynamic array of @int@.
    1524 @Array@ is an example of a \newterm{managed type} in \CFA, a type with a non-trivial constructor or destructor, or with a field of a managed type.
     1313In the example above, a \emph{default constructor} (\ie one with no parameters besides the @this@ parameter) and destructor are defined for the @Array@ struct, a dynamic array of @int@.
     1314@Array@ is an example of a \emph{managed type} in \CFA, a type with a non-trivial constructor or destructor, or with a field of a managed type.
    15251315As in the example, all instances of managed types are implicitly constructed upon allocation, and destructed upon deallocation; this ensures proper initialization and cleanup of resources contained in managed types, in this case the @data@ array on the heap.
    15261316The exact details of the placement of these implicit constructor and destructor calls are omitted here for brevity, the interested reader should consult \cite{Schluntz17}.
    15271317
    15281318Constructor calls are intended to seamlessly integrate with existing C initialization syntax, providing a simple and familiar syntax to veteran C programmers and allowing constructor calls to be inserted into legacy C code with minimal code changes.
    1529 As such, \CFA also provides syntax for \newterm{copy initialization} and \newterm{initialization parameters}:
     1319As such, \CFA also provides syntax for \emph{copy initialization} and \emph{initialization parameters}:
    15301320
    15311321\begin{cfa}
     
    15421332In addition to initialization syntax, \CFA provides two ways to explicitly call constructors and destructors.
    15431333Explicit calls to constructors double as a placement syntax, useful for construction of member fields in user-defined constructors and reuse of large storage allocations.
    1544 While the existing function-call syntax works for explicit calls to constructors and destructors, \CFA also provides a more concise \newterm{operator syntax} for both:
     1334While the existing function-call syntax works for explicit calls to constructors and destructors, \CFA also provides a more concise \emph{operator syntax} for both:
    15451335
    15461336\begin{cfa}
     
    15591349For compatibility with C, a copy constructor from the first union member type is also defined.
    15601350For @struct@ types, each of the four functions are implicitly defined to call their corresponding functions on each member of the struct.
    1561 To better simulate the behaviour of C initializers, a set of \newterm{field constructors} is also generated for structures.
     1351To better simulate the behaviour of C initializers, a set of \emph{field constructors} is also generated for structures.
    15621352A constructor is generated for each non-empty prefix of a structure's member-list which copy-constructs the members passed as parameters and default-constructs the remaining members.
    15631353To allow users to limit the set of constructors available for a type, when a user declares any constructor or destructor, the corresponding generated function and all field constructors for that type are hidden from expression resolution; similarly, the generated default constructor is hidden upon declaration of any constructor.
     
    15651355
    15661356In rare situations user programmers may not wish to have constructors and destructors called; in these cases, \CFA provides an ``escape hatch'' to not call them.
    1567 If a variable is initialized using the syntax \lstinline|S x @= {}| it will be an \newterm{unmanaged object}, and will not have constructors or destructors called.
     1357If a variable is initialized using the syntax \lstinline|S x @= {}| it will be an \emph{unmanaged object}, and will not have constructors or destructors called.
    15681358Any C initializer can be the right-hand side of an \lstinline|@=| initializer, \eg  \lstinline|Array a @= { 0, 0x0 }|, with the usual C initialization semantics.
    15691359In addition to the expressive power, \lstinline|@=| provides a simple path for migrating legacy C code to \CFA, by providing a mechanism to incrementally convert initializers; the \CFA design team decided to introduce a new syntax for this escape hatch because we believe that our RAII implementation will handle the vast majority of code in a desirable way, and we wished to maintain familiar syntax for this common case.
     
    15741364\section{Literals}
    15751365
    1576 C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and floating-point types are very similar, differing from each other only in suffix.
    1577 In keeping with the general \CFA approach of adding features while respecting ``the C way'' of doing things, we have extended both C's polymorphic zero and typed literal syntax to interoperate with user-defined types, while maintaining a backwards-compatible semantics.
    15781366
    15791367\subsection{0/1}
    15801368
    1581 In C, @0@ has the special property that it is the only ``false'' value; by the standard, any value which compares equal to @0@ is false, while any value that compares unequal to @0@ is true.
    1582 As such, an expression @x@ in any boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to an @&&@, @||@, or ternary operator) can be rewritten as @x != 0@ without changing its semantics.
    1583 The operator overloading feature of \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.
    1584 To provide this precision, \CFA introduces a new type @zero_t@ as type type of literal @0@ (somewhat analagous to @nullptr_t@ and @nullptr@ in \CCeleven); @zero_t@ can only take the value @0@, but has implicit conversions to the integer and pointer types so that standard C code involving @0@ continues to work properly.
    1585 With this addition, the \CFA compiler rewrites @if (x)@ and similar expressions to @if ((x) != 0)@ or the appropriate analogue, and any type @T@ can be made ``truthy'' by defining an operator overload @int ?!=?(T, zero_t)@.
    1586 \CC makes types truthy by adding a conversion to @bool@; prior to the addition of explicit cast operators in \CCeleven this approach had the pitfall of making truthy types transitively convertable to any numeric type; our design for \CFA avoids this issue.
    1587 
    1588 \CFA also includes a special type for @1@, @one_t@; like @zero_t@, @one_t@ has built-in implicit conversions to the various integral types so that @1@ maintains its expected semantics in legacy code.
    1589 The addition of @one_t@ allows generic algorithms to handle the unit value uniformly for types where that is meaningful.
    1590 \TODO{Make this sentence true} In particular, polymorphic functions in the \CFA prelude define @++x@ and @x++@ in terms of @x += 1@, allowing users to idiomatically define all forms of increment for a type @T@ by defining the single function @T& ?+=(T&, one_t)@; analogous overloads for the decrement operators are present as well.
     1369\TODO{Some text already at the end of Section~\ref{sec:poly-fns}}
     1370
    15911371
    15921372\subsection{Units}
     
    16171397\end{cfa}
    16181398}%
     1399
    16191400
    16201401\section{Evaluation}
     
    17921573Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable.
    17931574
    1794 There is ongoing work on a wide range of \CFA feature extensions, including arrays with size, exceptions, concurrent primitives, modules, and user-defined conversions.
     1575There is ongoing work on a wide range of \CFA feature extensions, including reference types, arrays with size, exceptions, concurrent primitives and modules.
    17951576(While all examples in the paper compile and run, a public beta-release of \CFA will take another 8--12 months to finalize these additional extensions.)
    17961577In addition, there are interesting future directions for the polymorphism design.
  • src/libcfa/Makefile.am

    rd56ca354 rc40e7c5  
    1010## Author           : Peter A. Buhr
    1111## Created On       : Sun May 31 08:54:01 2015
    12 ## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Fri Feb  9 15:51:24 2018
    14 ## Update Count     : 223
     12## Last Modified By : Andrew Beach
     13## Last Modified On : Wed Jul 26 14:15:00 2017
     14## Update Count     : 221
    1515###############################################################################
    1616
     
    9292libcfa_d_a_CFLAGS = -debug -O0 #No need for __CFA_DEBUG__ since we pass -debug
    9393
    94 stdhdr = ${shell find stdhdr -type f -printf "%p "}
     94stdhdr = ${shell echo stdhdr/*}
    9595
    9696cfa_includedir = $(CFA_INCDIR)
  • src/libcfa/bits/debug.c

    rd56ca354 rc40e7c5  
    1111// Last Modified By :
    1212// Last Modified On :
    13 // Update Count     : 1
     13// Update Count     : 0
    1414//
    1515
     
    4747        void __cfaabi_dbg_bits_release() __attribute__((__weak__)) {}
    4848
    49         void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
     49        void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format (printf, 1, 2) )) {
    5050                va_list args;
    5151
     
    6060        }
    6161
    62         void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
     62        void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format (printf, 1, 2) )) {
    6363                va_list args;
    6464
     
    7676        }
    7777
    78         void __cfaabi_dbg_bits_print_buffer( char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) )) {
     78        void __cfaabi_dbg_bits_print_buffer( char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format (printf, 3, 4) )) {
    7979                va_list args;
    8080
  • src/libcfa/bits/debug.h

    rd56ca354 rc40e7c5  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 12:35:19 2018
    13 // Update Count     : 2
     12// Last Modified On : Sat Jul 22 10:02:24 2017
     13// Update Count     : 1
    1414//
    1515
     
    4141      extern void __cfaabi_dbg_bits_acquire();
    4242      extern void __cfaabi_dbg_bits_release();
    43       extern void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
    44       extern void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
     43      extern void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format (printf, 1, 2) ));
     44      extern void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format (printf, 1, 2) ));
    4545      extern void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list arg );
    46       extern void __cfaabi_dbg_bits_print_buffer( char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) ));
     46      extern void __cfaabi_dbg_bits_print_buffer( char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format (printf, 3, 4) ));
    4747#ifdef __cforall
    4848}
  • src/libcfa/bits/defs.h

    rd56ca354 rc40e7c5  
    1010// Created On       : Thu Nov  9 13:24:10 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 16:22:41 2018
    13 // Update Count     : 8
     12// Last Modified On : Tue Jan  2 09:17:06 2018
     13// Update Count     : 2
    1414//
    1515
     
    3434
    3535#ifdef __cforall
    36 void abort ( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     36#ifndef __NO_ABORT_OVERLOAD
     37void abort ( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__));
     38#endif
    3739extern "C" {
    3840#endif
    39 void __cabi_abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     41void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__));
    4042#ifdef __cforall
    4143}
  • src/libcfa/concurrency/coroutine.c

    rd56ca354 rc40e7c5  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 16:10:31 2018
    13 // Update Count     : 4
     12// Last Modified On : Fri Jul 21 22:34:57 2017
     13// Update Count     : 1
    1414//
    1515
     
    7777                __cfaabi_dbg_debug_do(
    7878                        if ( mprotect( this.storage, pageSize, PROT_READ | PROT_WRITE ) == -1 ) {
    79                                 abort( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
     79                                abortf( "(coStack_t *)%p.^?{}() : internal error, mprotect failure, error(%d) %s.", &this, errno, strerror( errno ) );
    8080                        }
    8181                );
     
    9999// Wrapper for co
    100100void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
    101         disable_interrupts();
     101        // THREAD_GETMEM( This )->disableInterrupts();
    102102
    103103        // set state of current coroutine to inactive
     
    115115        src->state = Active;
    116116
    117         enable_interrupts( __cfaabi_dbg_ctx );
     117        // THREAD_GETMEM( This )->enableInterrupts();
    118118} //ctxSwitchDirect
    119119
     
    135135                __cfaabi_dbg_debug_do(
    136136                        if ( mprotect( storage, pageSize, PROT_NONE ) == -1 ) {
    137                                 abort( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) );
     137                                abortf( "(uMachContext &)%p.createContext() : internal error, mprotect failure, error(%d) %s.", this, (int)errno, strerror( (int)errno ) );
    138138                        } // if
    139139                );
    140140
    141141                if ( (intptr_t)storage == 0 ) {
    142                         abort( "Attempt to allocate %zd bytes of storage for coroutine or task execution-state but insufficient memory available.", size );
     142                        abortf( "Attempt to allocate %d bytes of storage for coroutine or task execution-state but insufficient memory available.", size );
    143143                } // if
    144144
  • src/libcfa/concurrency/invoke.c

    rd56ca354 rc40e7c5  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  9 16:37:42 2018
    13 // Update Count     : 5
     12// Last Modified On : Tue Feb  6 23:00:57 2018
     13// Update Count     : 3
    1414//
    1515
     
    5151        //Final suspend, should never return
    5252        __leave_coroutine();
    53         __cabi_abort( "Resumed dead coroutine" );
     53        abortf( "Resumed dead coroutine" );
    5454}
    5555
     
    8181        //Final suspend, should never return
    8282        __leave_thread_monitor( thrd );
    83         __cabi_abort( "Resumed dead thread" );
     83        abortf( "Resumed dead thread" );
    8484}
    8585
     
    9393        struct coStack_t* stack = &get_coroutine( this )->stack;
    9494
    95 #if defined( __i386 )
     95#if defined( __i386__ )
    9696
    9797        struct FakeStack {
     
    114114        ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F;  //Vol. 1 8-7
    115115
    116 #elif defined( __x86_64 )
     116#elif defined( __x86_64__ )
    117117
    118118        struct FakeStack {
     
    150150        fs->arg[0] = this;
    151151        fs->arg[1] = invoke;
    152 
    153152#else
    154         #error uknown hardware architecture
     153        #error Only __i386__ and __x86_64__ is supported for threads in cfa
    155154#endif
    156155}
  • src/libcfa/concurrency/invoke.h

    rd56ca354 rc40e7c5  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  9 14:41:55 2018
    13 // Update Count     : 6
     12// Last Modified On : Tue Jan 23 14:55:46 2018
     13// Update Count     : 3
    1414//
    1515
     
    202202        void CtxSwitch( void * from, void * to ) asm ("CtxSwitch");
    203203
    204         #if   defined( __i386 )
     204        #if   defined( __x86_64__ )
     205        #define CtxGet( ctx ) __asm__ ( \
     206                        "movq %%rsp,%0\n"   \
     207                        "movq %%rbp,%1\n"   \
     208                : "=rm" (ctx.SP), "=rm" (ctx.FP) )
     209        #elif defined( __i386__ )
    205210        #define CtxGet( ctx ) __asm__ ( \
    206211                        "movl %%esp,%0\n"   \
    207212                        "movl %%ebp,%1\n"   \
    208                 : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    209         #elif defined( __x86_64 )
    210         #define CtxGet( ctx ) __asm__ ( \
    211                         "movq %%rsp,%0\n"   \
    212                         "movq %%rbp,%1\n"   \
    213213                : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    214214        #elif defined( __ARM_ARCH )
     
    217217                        "mov %1,%%r11\n"   \
    218218                : "=rm" (ctx.SP), "=rm" (ctx.FP) )
    219         #else
    220                 #error unknown hardware architecture
    221219        #endif
    222220
  • src/libcfa/concurrency/kernel.c

    rd56ca354 rc40e7c5  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 23:52:19 2018
    13 // Update Count     : 5
     12// Last Modified On : Tue Feb  6 21:51:26 2018
     13// Update Count     : 4
    1414//
    1515
    1616//C Includes
    1717#include <stddef.h>
     18#define ftype `ftype`
    1819extern "C" {
    1920#include <stdio.h>
     
    2324#include <unistd.h>
    2425}
     26#undef ftype
    2527
    2628//CFA Includes
  • src/libcfa/concurrency/monitor.c

    rd56ca354 rc40e7c5  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 16:12:20 2018
    13 // Update Count     : 4
     12// Last Modified On : Mon Jul 31 14:59:05 2017
     13// Update Count     : 3
    1414//
    1515
     
    8787                thread_desc * thrd = this_thread;
    8888
    89                 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
     89                __cfaabi_dbg_print_safe("Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    9090
    9191                if( !this->owner ) {
     
    9393                        set_owner( this, thrd );
    9494
    95                         __cfaabi_dbg_print_safe( "Kernel :  mon is free \n" );
     95                        __cfaabi_dbg_print_safe("Kernel :  mon is free \n");
    9696                }
    9797                else if( this->owner == thrd) {
     
    9999                        this->recursion += 1;
    100100
    101                         __cfaabi_dbg_print_safe( "Kernel :  mon already owned \n" );
     101                        __cfaabi_dbg_print_safe("Kernel :  mon already owned \n");
    102102                }
    103103                else if( is_accepted( this, group) ) {
     
    108108                        reset_mask( this );
    109109
    110                         __cfaabi_dbg_print_safe( "Kernel :  mon accepts \n" );
     110                        __cfaabi_dbg_print_safe("Kernel :  mon accepts \n");
    111111                }
    112112                else {
    113                         __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
     113                        __cfaabi_dbg_print_safe("Kernel :  blocking \n");
    114114
    115115                        // Some one else has the monitor, wait in line for it
     
    118118                        BlockInternal( &this->lock );
    119119
    120                         __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     120                        __cfaabi_dbg_print_safe("Kernel : %10p Entered  mon %p\n", thrd, this);
    121121
    122122                        // BlockInternal will unlock spinlock, no need to unlock ourselves
     
    124124                }
    125125
    126                 __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     126                __cfaabi_dbg_print_safe("Kernel : %10p Entered  mon %p\n", thrd, this);
    127127
    128128                // Release the lock and leave
     
    136136                thread_desc * thrd = this_thread;
    137137
    138                 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     138                __cfaabi_dbg_print_safe("Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
    139139
    140140
    141141                if( !this->owner ) {
    142                         __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
     142                        __cfaabi_dbg_print_safe("Kernel : Destroying free mon %p\n", this);
    143143
    144144                        // No one has the monitor, just take it
     
    151151                        // We already have the monitor... but where about to destroy it so the nesting will fail
    152152                        // Abort!
    153                         abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex." );
     153                        abortf("Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.");
    154154                }
    155155
     
    158158                __monitor_group_t group = { &this, 1, func };
    159159                if( is_accepted( this, group) ) {
    160                         __cfaabi_dbg_print_safe( "Kernel :  mon accepts dtor, block and signal it \n" );
     160                        __cfaabi_dbg_print_safe("Kernel :  mon accepts dtor, block and signal it \n");
    161161
    162162                        // Wake the thread that is waiting for this
     
    177177                }
    178178                else {
    179                         __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
     179                        __cfaabi_dbg_print_safe("Kernel :  blocking \n");
    180180
    181181                        wait_ctx( this_thread, 0 )
     
    190190                }
    191191
    192                 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
     192                __cfaabi_dbg_print_safe("Kernel : Destroying %p\n", this);
    193193
    194194        }
     
    199199                lock( this->lock __cfaabi_dbg_ctx2 );
    200200
    201                 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner);
     201                __cfaabi_dbg_print_safe("Kernel : %10p Leaving mon %p (%p)\n", this_thread, this, this->owner);
    202202
    203203                verifyf( this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", this_thread, this->owner, this->recursion, this );
     
    209209                // it means we don't need to do anything
    210210                if( this->recursion != 0) {
    211                         __cfaabi_dbg_print_safe( "Kernel :  recursion still %d\n", this->recursion);
     211                        __cfaabi_dbg_print_safe("Kernel :  recursion still %d\n", this->recursion);
    212212                        unlock( this->lock );
    213213                        return;
     
    228228                __cfaabi_dbg_debug_do(
    229229                        if( this_thread != this->owner ) {
    230                                 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, this_thread, this->owner);
     230                                abortf("Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, this_thread, this->owner);
    231231                        }
    232232                        if( this->recursion != 1 ) {
    233                                 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
     233                                abortf("Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
    234234                        }
    235235                )
     
    256256                // If we haven't left the last level of recursion
    257257                // it must mean there is an error
    258                 if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); }
     258                if( this->recursion != 0) { abortf("Thread internal monitor has unbalanced recursion"); }
    259259
    260260                // Fetch the next thread, can be null
     
    302302        (this_thread->monitors){m, count, func};
    303303
    304         // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count);
     304        // __cfaabi_dbg_print_safe("MGUARD : enter %d\n", count);
    305305
    306306        // Enter the monitors in order
     
    308308        enter( group );
    309309
    310         // __cfaabi_dbg_print_safe( "MGUARD : entered\n" );
     310        // __cfaabi_dbg_print_safe("MGUARD : entered\n");
    311311}
    312312
     
    314314// Dtor for monitor guard
    315315void ^?{}( monitor_guard_t & this ) {
    316         // __cfaabi_dbg_print_safe( "MGUARD : leaving %d\n", this.count);
     316        // __cfaabi_dbg_print_safe("MGUARD : leaving %d\n", this.count);
    317317
    318318        // Leave the monitors in order
    319319        leave( this.m, this.count );
    320320
    321         // __cfaabi_dbg_print_safe( "MGUARD : left\n" );
     321        // __cfaabi_dbg_print_safe("MGUARD : left\n");
    322322
    323323        // Restore thread context
     
    427427                thread_desc * this_thrd = this_thread;
    428428                if ( this.monitor_count != this_thrd->monitors.size ) {
    429                         abort( "Signal on condition %p made with different number of monitor(s), expected %i got %i", &this, this.monitor_count, this_thrd->monitors.size );
     429                        abortf( "Signal on condition %p made with different number of monitor(s), expected %i got %i", &this, this.monitor_count, this_thrd->monitors.size );
    430430                }
    431431
    432432                for(int i = 0; i < this.monitor_count; i++) {
    433433                        if ( this.monitors[i] != this_thrd->monitors[i] ) {
    434                                 abort( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors[i] );
     434                                abortf( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors[i] );
    435435                        }
    436436                }
     
    534534        if(actual_count == 0) return;
    535535
    536         __cfaabi_dbg_print_buffer_local( "Kernel : waitfor internal proceeding\n" );
     536        __cfaabi_dbg_print_buffer_local( "Kernel : waitfor internal proceeding\n");
    537537
    538538        // Create storage for monitor context
     
    551551                        __acceptable_t& accepted = mask[index];
    552552                        if( accepted.is_dtor ) {
    553                                 __cfaabi_dbg_print_buffer_local( "Kernel : dtor already there\n" );
     553                                __cfaabi_dbg_print_buffer_local( "Kernel : dtor already there\n");
    554554                                verifyf( accepted.size == 1,  "ERROR: Accepted dtor has more than 1 mutex parameter." );
    555555
     
    563563                        }
    564564                        else {
    565                                 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, baton-passing\n" );
     565                                __cfaabi_dbg_print_buffer_local( "Kernel : thread present, baton-passing\n");
    566566
    567567                                // Create the node specific to this wait operation
     
    577577                                        }
    578578                                #endif
    579                                 __cfaabi_dbg_print_buffer_local( "\n" );
     579                                __cfaabi_dbg_print_buffer_local( "\n");
    580580
    581581                                // Set the owners to be the next thread
     
    588588                                monitor_restore;
    589589
    590                                 __cfaabi_dbg_print_buffer_local( "Kernel : thread present, returned\n" );
     590                                __cfaabi_dbg_print_buffer_local( "Kernel : thread present, returned\n");
    591591                        }
    592592
     
    598598
    599599        if( duration == 0 ) {
    600                 __cfaabi_dbg_print_buffer_local( "Kernel : non-blocking, exiting\n" );
     600                __cfaabi_dbg_print_buffer_local( "Kernel : non-blocking, exiting\n");
    601601
    602602                unlock_all( locks, count );
     
    607607
    608608
    609         verifyf( duration < 0, "Timeout on waitfor statments not supported yet." );
    610 
    611         __cfaabi_dbg_print_buffer_local( "Kernel : blocking waitfor\n" );
     609        verifyf( duration < 0, "Timeout on waitfor statments not supported yet.");
     610
     611        __cfaabi_dbg_print_buffer_local( "Kernel : blocking waitfor\n");
    612612
    613613        // Create the node specific to this wait operation
     
    631631        monitor_restore;
    632632
    633         __cfaabi_dbg_print_buffer_local( "Kernel : exiting\n" );
     633        __cfaabi_dbg_print_buffer_local( "Kernel : exiting\n");
    634634
    635635        __cfaabi_dbg_print_buffer_local( "Kernel : accepted %d\n", *mask.accepted);
     
    640640
    641641static inline void set_owner( monitor_desc * this, thread_desc * owner ) {
    642         // __cfaabi_dbg_print_safe( "Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
     642        // __cfaabi_dbg_print_safe("Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
    643643
    644644        //Pass the monitor appropriately
     
    672672static inline thread_desc * next_thread( monitor_desc * this ) {
    673673        //Check the signaller stack
    674         __cfaabi_dbg_print_safe( "Kernel :  mon %p AS-stack top %p\n", this, this->signal_stack.top);
     674        __cfaabi_dbg_print_safe("Kernel :  mon %p AS-stack top %p\n", this, this->signal_stack.top);
    675675        __condition_criterion_t * urgent = pop( this->signal_stack );
    676676        if( urgent ) {
     
    814814        thread_desc * thrd = this_thread;
    815815        if( !this.monitors ) {
    816                 // __cfaabi_dbg_print_safe( "Branding\n" );
     816                // __cfaabi_dbg_print_safe("Branding\n");
    817817                assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data );
    818818                this.monitor_count = thrd->monitors.size;
  • src/libcfa/concurrency/preemption.c

    rd56ca354 rc40e7c5  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  9 16:38:13 2018
    13 // Update Count     : 14
     12// Last Modified On : Tue Feb  6 15:00:36 2018
     13// Update Count     : 10
    1414//
    1515
    1616#include "preemption.h"
    1717
     18#define ftype `ftype`
    1819extern "C" {
    1920#include <errno.h>
     
    2223#include <unistd.h>
    2324}
     25#undef ftype
    2426
    2527#include "bits/signal.h"
     
    4850
    4951// Machine specific register name
    50 #if   defined( __i386 )
     52#if   defined(__x86_64__)
     53#define CFA_REG_IP gregs[REG_RIP]
     54#elif defined(__i386__)
    5155#define CFA_REG_IP gregs[REG_EIP]
    52 #elif defined( __x86_64 )
    53 #define CFA_REG_IP gregs[REG_RIP]
    54 #elif defined( __ARM_ARCH )
     56#elif defined(__ARM_ARCH__)
    5557#define CFA_REG_IP arm_pc
    56 #else
    57 #error unknown hardware architecture
    5858#endif
    5959
     
    197197
    198198        if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
    199             abort( "internal error, pthread_sigmask" );
     199            abortf( "internal error, pthread_sigmask" );
    200200        }
    201201}
     
    208208
    209209        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
    210             abort( "internal error, pthread_sigmask" );
     210            abortf( "internal error, pthread_sigmask" );
    211211        }
    212212}
     
    247247// Called from kernel_startup
    248248void kernel_start_preemption() {
    249         __cfaabi_dbg_print_safe( "Kernel : Starting preemption\n" );
     249        __cfaabi_dbg_print_safe("Kernel : Starting preemption\n");
    250250
    251251        // Start with preemption disabled until ready
     
    268268// Called from kernel_shutdown
    269269void kernel_stop_preemption() {
    270         __cfaabi_dbg_print_safe( "Kernel : Preemption stopping\n" );
     270        __cfaabi_dbg_print_safe("Kernel : Preemption stopping\n");
    271271
    272272        // Block all signals since we are already shutting down
     
    284284        // Preemption is now fully stopped
    285285
    286         __cfaabi_dbg_print_safe( "Kernel : Preemption stopped\n" );
     286        __cfaabi_dbg_print_safe("Kernel : Preemption stopped\n");
    287287}
    288288
     
    322322                case PREEMPT_TERMINATE: verify(this_processor->do_terminate);
    323323                default:
    324                         abort( "internal error, signal value is %d", sfp->si_value.sival_int );
     324                        abortf( "internal error, signal value is %d", sfp->si_value.sival_int );
    325325        }
    326326
     
    328328        if( !preemption_ready() ) { return; }
    329329
    330         __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
     330        __cfaabi_dbg_print_buffer_decl(" KERNEL: preempting core %p (%p).\n", this_processor, this_thread);
    331331
    332332        preemption_in_progress = true;                      // Sync flag : prevent recursive calls to the signal handler
     
    348348
    349349        if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
    350             abort( "internal error, pthread_sigmask" );
     350            abortf( "internal error, pthread_sigmask" );
    351351        }
    352352
     
    365365                                        continue;
    366366                        case EINVAL :
    367                                         abort( "Timeout was invalid." );
     367                                        abortf("Timeout was invalid.");
    368368                                default:
    369                                         abort( "Unhandled error %d", err);
     369                                        abortf("Unhandled error %d", err);
    370370                        }
    371371                }
     
    374374                assertf(sig == SIGALRM, "Kernel Internal Error, sigwait: Unexpected signal %d (%d : %d)\n", sig, info.si_code, info.si_value.sival_int);
    375375
    376                 // __cfaabi_dbg_print_safe( "Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );
     376                // __cfaabi_dbg_print_safe("Kernel : Caught alarm from %d with %d\n", info.si_code, info.si_value.sival_int );
    377377                // Switch on the code (a.k.a. the sender) to
    378378                switch( info.si_code )
     
    382382                case SI_TIMER:
    383383                case SI_KERNEL:
    384                         // __cfaabi_dbg_print_safe( "Kernel : Preemption thread tick\n" );
     384                        // __cfaabi_dbg_print_safe("Kernel : Preemption thread tick\n");
    385385                        lock( event_kernel->lock __cfaabi_dbg_ctx2 );
    386386                        tick_preemption();
     
    396396
    397397EXIT:
    398         __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
     398        __cfaabi_dbg_print_safe("Kernel : Preemption thread stopping\n");
    399399        return NULL;
    400400}
  • src/libcfa/exception.c

    rd56ca354 rc40e7c5  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Jun 26 15:13:00 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb  9 14:41:55 2018
    13 // Update Count     : 8
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Aug 17 15:45:00 2017
     13// Update Count     : 7
    1414//
    1515
     
    453453// match, which is no way generic.  Some more works need to be done if we want to have a single call to the try routine.
    454454
    455 #if defined( __i386 ) || defined( __x86_64 )
     455#if defined( __x86_64__ ) || defined( __i386__ )
    456456asm (
    457457        //HEADER
     
    476476//      "       .section        .note.GNU-stack,\"x\",@progbits\n"
    477477);
    478 #endif // __i386 || __x86_64
     478#endif // __x86_64__ || __i386__
  • src/libcfa/interpose.c

    rd56ca354 rc40e7c5  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 16:18:09 2018
    13 // Update Count     : 75
     12// Last Modified On : Wed Feb  7 09:05:18 2018
     13// Update Count     : 59
    1414//
    1515
     
    2828}
    2929
     30#define __NO_ABORT_OVERLOAD // no abort overload avoid ambiguities
    3031#include "bits/debug.h"
    3132#include "bits/defs.h"
     
    5051                        error = dlerror();
    5152                        if ( error ) {
    52                                 abort( "interpose_symbol : failed to open libc, %s\n", error );
     53                                abortf( "interpose_symbol : failed to open libc, %s\n", error );
    5354                        }
    5455                #endif
     
    6869
    6970        error = dlerror();
    70         if ( error ) abort( "interpose_symbol : internal error, %s\n", error );
     71        if ( error ) abortf( "interpose_symbol : internal error, %s\n", error );
    7172
    7273        return originalFunc.fptr;
     
    9798
    9899struct {
    99         void (* exit)( int ) __attribute__ (( __noreturn__ ));
    100         void (* abort)( void ) __attribute__ (( __noreturn__ ));
     100        __typeof__( exit  ) exit  __attribute__(( noreturn ));
     101        __typeof__( abort ) abort __attribute__(( noreturn ));
    101102} __cabi_libc;
    102103
     
    122123
    123124// Forward declare abort after the __typeof__ call to avoid ambiguities
    124 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    125 void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     125void abort ( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__));
    126126
    127127extern "C" {
    128         void abort( void ) __attribute__ (( __nothrow__, __leaf__, __noreturn__ )) {
    129                 abort( NULL );
    130         }
    131 
    132         void __cabi_abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
     128        void abort( void ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
     129                abortf( NULL );
     130        }
     131
     132        void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
    133133                va_list argp;
    134134                va_start( argp, fmt );
     
    137137        }
    138138
    139         void exit( int status ) __attribute__ (( __nothrow__, __leaf__, __noreturn__ )) {
    140                 __cabi_libc.exit( status );
    141         }
    142 }
    143 
    144 void * kernel_abort    ( void ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) { return NULL; }
    145 void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) {}
    146 int kernel_abort_lastframe( void ) __attribute__ (( __nothrow__, __leaf__, __weak__ )) { return 4; }
     139        void exit( int __status ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
     140                __cabi_libc.exit(__status);
     141        }
     142}
     143
     144void * kernel_abort    ( void ) __attribute__ ((__nothrow__, __leaf__, __weak__)) { return NULL; }
     145void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__ ((__nothrow__, __leaf__, __weak__)) {}
     146int kernel_abort_lastframe( void ) __attribute__ ((__nothrow__, __leaf__, __weak__)) { return 4; }
    147147
    148148enum { abort_text_size = 1024 };
     
    150150static int abort_lastframe;
    151151
    152 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) {
    153     va_list args;
    154     va_start( args, fmt );
    155     vfprintf( stderr, fmt, args );
    156     va_end( args );
    157         __cabi_libc.exit( status );
    158 }
    159 
    160 void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
     152void abort( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
    161153        void * kernel_data = kernel_abort();                    // must be done here to lock down kernel
    162154        int len;
     
    234226
    235227void sigHandler_segv( __CFA_SIGPARMS__ ) {
    236         abort( "Addressing invalid memory at location %p\n"
     228        abortf( "Addressing invalid memory at location %p\n"
    237229                        "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript.\n",
    238230                        sfp->si_addr );
     
    240232
    241233void sigHandler_ill( __CFA_SIGPARMS__ ) {
    242         abort( "Executing illegal instruction at location %p.\n"
     234        abortf( "Executing illegal instruction at location %p.\n"
    243235                        "Possible cause is stack corruption.\n",
    244236                        sfp->si_addr );
     
    256248          default: msg = "unknown";
    257249        } // choose
    258         abort( "Computation error %s at location %p.\n", msg, sfp->si_addr );
     250        abortf( "Computation error %s at location %p.\n", msg, sfp->si_addr );
    259251}
    260252
  • src/prelude/builtins.c

    rd56ca354 rc40e7c5  
    99// Author           : Peter A. Buhr
    1010// Created On       : Fri Jul 21 16:21:03 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 12:47:59 2018
    13 // Update Count     : 19
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tus Jul 25 15:33:00 2017
     13// Update Count     : 14
    1414//
    1515
     
    2020#include "../libcfa/virtual.h"
    2121#include "../libcfa/exception.h"
    22 
    23 void exit( int status, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    24 void abort ( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
    2522
    2623// exponentiation operator implementation
  • src/tests/preempt_longrun/Makefile.am

    rd56ca354 rc40e7c5  
    1818max_time=600
    1919preempt=1_000ul
    20 debug=-debug
    2120
    2221REPEAT = ${abs_top_srcdir}/tools/repeat
    2322TIME = /usr/bin/time -f "%E"
    2423
    25 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt}
     24BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -debug -O2 -DPREEMPTION_RATE=${preempt}
    2625CFLAGS = ${BUILD_FLAGS}
    2726CC = @CFA_BINDIR@/@CFA_NAME@
    2827
    29 TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
     28TESTS = block create disjoint enter enter3 processor stack wait yield
    3029
    3130.INTERMEDIATE: ${TESTS}
     
    3736
    3837% : %.c ${CC}
    39         ${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
     38        ${AM_V_GEN}${CC} ${CFLAGS} ${<} -o ${@}
    4039
    4140%.run : % ${REPEAT}
  • src/tests/preempt_longrun/Makefile.in

    rd56ca354 rc40e7c5  
    451451max_time = 600
    452452preempt = 1_000ul
    453 debug = -debug
    454453REPEAT = ${abs_top_srcdir}/tools/repeat
    455454TIME = /usr/bin/time -f "%E"
    456 BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -O2 -DPREEMPTION_RATE=${preempt}
    457 TESTS = block coroutine create disjoint enter enter3 processor stack wait yield
     455BUILD_FLAGS = -g -Wall -Wno-unused-function -quiet @CFA_FLAGS@ -debug -O2 -DPREEMPTION_RATE=${preempt}
     456TESTS = block create disjoint enter enter3 processor stack wait yield
    458457all: all-am
    459458
     
    644643        $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
    645644        "$$tst" $(AM_TESTS_FD_REDIRECT)
    646 coroutine.log: coroutine
    647         @p='coroutine'; \
    648         b='coroutine'; \
    649         $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
    650         --log-file $$b.log --trs-file $$b.trs \
    651         $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
    652         "$$tst" $(AM_TESTS_FD_REDIRECT)
    653645create.log: create
    654646        @p='create'; \
     
    881873
    882874% : %.c ${CC}
    883         ${AM_V_GEN}${CC} ${CFLAGS} ${<} $(debug) -o ${@}
     875        ${AM_V_GEN}${CC} ${CFLAGS} ${<} -o ${@}
    884876
    885877%.run : % ${REPEAT}
Note: See TracChangeset for help on using the changeset viewer.