Changes in / [7323573:5f95b5f]


Ignore:
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • doc/papers/general/Paper.tex

    r7323573 r5f95b5f  
    3939\newcommand{\TODO}[1]{\textbf{TODO}: {\itshape #1}} % TODO included
    4040%\newcommand{\TODO}[1]{} % TODO elided
     41
    4142% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    42 % removes it as a variable-name character so keyworks in variables are highlighted
    43 \DeclareTextCommandDefault{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}
     43% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     44% AFTER HYPERREF.
     45%\DeclareTextCommandDefault{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}
     46\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    4447
    4548\makeatletter
     
    4952\setlength{\parindentlnth}{\parindent}
    5053
     54\newcommand{\LstKeywordStyle}[1]{{\lst@basicstyle{\lst@keywordstyle{#1}}}}
     55\newcommand{\LstCommentStyle}[1]{{\lst@basicstyle{\lst@commentstyle{#1}}}}
     56
    5157\newlength{\gcolumnposn}                                % temporary hack because lstlisting does not handle tabs correctly
    5258\newlength{\columnposn}
    5359\setlength{\gcolumnposn}{2.75in}
    5460\setlength{\columnposn}{\gcolumnposn}
    55 \newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@commentstyle{#2}}}
     61\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
    5662\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
     63
     64% Denote newterms in particular font and index them without particular font and in lowercase, e.g., \newterm{abc}.
     65% The option parameter provides an index term different from the new term, e.g., \newterm[\texttt{abc}]{abc}
     66% The star version does not lowercase the index information, e.g., \newterm*{IBM}.
     67\newcommand{\newtermFontInline}{\emph}
     68\newcommand{\newterm}{\@ifstar\@snewterm\@newterm}
     69\newcommand{\@newterm}[2][\@empty]{\lowercase{\def\temp{#2}}{\newtermFontInline{#2}}\ifx#1\@empty\index{\temp}\else\index{#1@{\protect#2}}\fi}
     70\newcommand{\@snewterm}[2][\@empty]{{\newtermFontInline{#2}}\ifx#1\@empty\index{#2}\else\index{#1@{\protect#2}}\fi}
    5771
    5872% Latin abbreviation
    5973\newcommand{\abbrevFont}{\textit}       % set empty for no italics
     74\newcommand{\EG}{\abbrevFont{e}.\abbrevFont{g}.}
    6075\newcommand*{\eg}{%
    61         \@ifnextchar{,}{\abbrevFont{e}.\abbrevFont{g}.}%
    62                 {\@ifnextchar{:}{\abbrevFont{e}.\abbrevFont{g}.}%
    63                         {\abbrevFont{e}.\abbrevFont{g}.,\xspace}}%
     76        \@ifnextchar{,}{\EG}%
     77                {\@ifnextchar{:}{\EG}%
     78                        {\EG,\xspace}}%
    6479}%
     80\newcommand{\IE}{\abbrevFont{i}.\abbrevFont{e}.}
    6581\newcommand*{\ie}{%
    66         \@ifnextchar{,}{\abbrevFont{i}.\abbrevFont{e}.}%
    67                 {\@ifnextchar{:}{\abbrevFont{i}.\abbrevFont{e}.}%
    68                         {\abbrevFont{i}.\abbrevFont{e}.,\xspace}}%
     82        \@ifnextchar{,}{\IE}%
     83                {\@ifnextchar{:}{\IE}%
     84                        {\IE,\xspace}}%
    6985}%
     86\newcommand{\ETC}{\abbrevFont{etc}}
    7087\newcommand*{\etc}{%
    71         \@ifnextchar{.}{\abbrevFont{etc}}%
    72         {\abbrevFont{etc}.\xspace}%
     88        \@ifnextchar{.}{\ETC}%
     89        {\ETC\xspace}%
    7390}%
    74 \newcommand{\etal}{%
    75         \@ifnextchar{.}{\abbrevFont{et~al}}%
    76                 {\abbrevFont{et al}.\xspace}%
     91\newcommand{\ETAL}{\abbrevFont{et}\hspace{2pt}\abbrevFont{al}}
     92\newcommand*{\etal}{%
     93        \@ifnextchar{.}{\protect\ETAL}%
     94                {\abbrevFont{\protect\ETAL}.\xspace}%
     95}%
     96\newcommand{\VIZ}{\abbrevFont{viz}}
     97\newcommand*{\viz}{%
     98        \@ifnextchar{.}{\VIZ}%
     99                {\abbrevFont{\VIZ}.\xspace}%
    77100}%
    78101\makeatother
     
    80103% CFA programming language, based on ANSI C (with some gcc additions)
    81104\lstdefinelanguage{CFA}[ANSI]{C}{
    82         morekeywords={_Alignas,_Alignof,__alignof,__alignof__,asm,__asm,__asm__,_At,_Atomic,__attribute,__attribute__,auto,
    83                 _Bool,catch,catchResume,choose,_Complex,__complex,__complex__,__const,__const__,disable,dtype,enable,__extension__,
    84                 fallthrough,fallthru,finally,forall,ftype,_Generic,_Imaginary,inline,__label__,lvalue,_Noreturn,one_t,otype,restrict,_Static_assert,
    85                 _Thread_local,throw,throwResume,trait,try,ttype,typeof,__typeof,__typeof__,zero_t},
     105        morekeywords={
     106                _Alignas, _Alignof, __alignof, __alignof__, asm, __asm, __asm__, _At, __attribute,
     107                __attribute__, auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__,
     108                __const, __const__, disable, dtype, enable, __extension__, fallthrough, fallthru,
     109                finally, forall, ftype, _Generic, _Imaginary, inline, __label__, lvalue, _Noreturn, one_t,
     110                otype, restrict, _Static_assert, throw, throwResume, trait, try, ttype, typeof, __typeof,
     111                __typeof__, virtual, with, zero_t},
     112        moredirectives={defined,include_next}%
    86113}%
    87114
     
    91118basicstyle=\linespread{0.9}\sf,                                                 % reduce line spacing and use sanserif font
    92119stringstyle=\tt,                                                                                % use typewriter font
    93 tabsize=4,                                                                                              % 4 space tabbing
     120tabsize=5,                                                                                              % N space tabbing
    94121xleftmargin=\parindentlnth,                                                             % indent code to paragraph indentation
    95122%mathescape=true,                                                                               % LaTeX math escape in CFA code $...$
     
    101128belowskip=3pt,
    102129% replace/adjust listing characters that look bad in sanserif
    103 literate={-}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.06ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     130literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    104131        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    105         {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1.4ex][c]{\raisebox{0.5ex}{\rule{1.2ex}{0.06ex}}}\kern-0.3ex\textgreater}2,
     132        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
    106133moredelim=**[is][\color{red}]{`}{`},
    107134}% lstset
     
    109136% inline code @...@
    110137\lstMakeShortInline@%
     138
     139\lstnewenvironment{cfa}[1][]
     140{\lstset{#1}}
     141{}
     142\lstnewenvironment{C++}[1][]                            % use C++ style
     143{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}\lstset{#1}}
     144{}
     145
    111146
    112147\title{Generic and Tuple Types with Efficient Dynamic Layout in \protect\CFA}
     
    148183The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems to hobby projects.
    149184This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    150 The \cite{TIOBE} ranks the top 5 most popular programming languages as: Java 16\%, \Textbf{C 7\%}, \Textbf{\CC 5\%}, \Csharp 4\%, Python 4\% = 36\%, where the next 50 languages are less than 3\% each with a long tail.
     185The TIOBE~\cite{TIOBE} ranks the top 5 most popular programming languages as: Java 16\%, \Textbf{C 7\%}, \Textbf{\CC 5\%}, \Csharp 4\%, Python 4\% = 36\%, where the next 50 languages are less than 3\% each with a long tail.
    151186The top 3 rankings over the past 30 years are:
    152187\lstDeleteShortInline@%
     
    185220\label{sec:poly-fns}
    186221
    187 \CFA{}\hspace{1pt}'s polymorphism was originally formalized by \cite{Ditchfield92}, and first implemented by \cite{Bilson03}.
     222\CFA{}\hspace{1pt}'s polymorphism was originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.
    188223The signature feature of \CFA is parametric-polymorphic functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a @forall@ clause (giving the language its name):
    189224\begin{lstlisting}
     
    258293}
    259294\end{lstlisting}
    260 Within the block, the nested version of @<@ performs @>@ and this local version overrides the built-in @<@ so it is passed to @qsort@.
     295Within the block, the nested version of @?<?@ performs @?>?@ and this local version overrides the built-in @?<?@ so it is passed to @qsort@.
    261296Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types.
    262297
     
    544579p`->0` = 5;                                                                     $\C{// change quotient}$
    545580bar( qr`.1`, qr );                                                      $\C{// pass remainder and quotient/remainder}$
    546 rem = [42, div( 13, 5 )]`.0.1`;                         $\C{// access 2nd component of 1st component of tuple expression}$
     581rem = [div( 13, 5 ), 42]`.0.1`;                         $\C{// access 2nd component of 1st component of tuple expression}$
    547582\end{lstlisting}
    548583
     
    730765\end{lstlisting}
    731766Hence, function parameter and return lists are flattened for the purposes of type unification allowing the example to pass expression resolution.
    732 This relaxation is possible by extending the thunk scheme described by~\cite{Bilson03}.
     767This relaxation is possible by extending the thunk scheme described by Bilson~\cite{Bilson03}.
    733768Whenever a candidate's parameter structure does not exactly match the formal parameter's structure, a thunk is generated to specialize calls to the actual function:
    734769\begin{lstlisting}
     
    902937
    903938
     939\section{Control Structures}
     940
     941
     942\subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break}}{Labelled continue / break}}
     943
     944While C provides @continue@ and @break@ statements for altering control flow, both are restricted to one level of nesting for a particular control structure.
     945Unfortunately, this restriction forces programmers to use @goto@ to achieve the equivalent control-flow for more than one level of nesting.
     946To prevent having to switch to the @goto@, \CFA extends the @continue@ and @break@ with a target label to support static multi-level exit~\cite{Buhr85}, as in Java.
     947For both @continue@ and @break@, the target label must be directly associated with a @for@, @while@ or @do@ statement;
     948for @break@, the target label can also be associated with a @switch@, @if@ or compound (@{}@) statement.
     949Figure~\ref{f:MultiLevelExit} shows @continue@ and @break@ indicating the specific control structure, and the corresponding C program using only @goto@ and labels.
     950The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 nested control-structures.
     951
     952\begin{figure}
     953\lstDeleteShortInline@%
     954\begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     955\multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}   & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
     956\begin{cfa}
     957`LC:` {
     958        ... $declarations$ ...
     959        `LS:` switch ( ... ) {
     960          case 3:
     961                `LIF:` if ( ... ) {
     962                        `LF:` for ( ... ) {
     963                                `LW:` while ( ... ) {
     964                                        ... break `LC`; ...
     965                                        ... break `LS`; ...
     966                                        ... break `LIF`; ...
     967                                        ... continue `LF;` ...
     968                                        ... break `LF`; ...
     969                                        ... continue `LW`; ...
     970                                        ... break `LW`; ...
     971                                } // while
     972                        } // for
     973                } else {
     974                        ... break `LIF`; ...
     975                } // if
     976        } // switch
     977} // compound
     978\end{cfa}
     979&
     980\begin{cfa}
     981{
     982        ... $declarations$ ...
     983        switch ( ... ) {
     984          case 3:
     985                if ( ... ) {
     986                        for ( ... ) {
     987                                while ( ... ) {
     988                                        ... goto `LC`; ...
     989                                        ... goto `LS`; ...
     990                                        ... goto `LIF`; ...
     991                                        ... goto `LFC`; ...
     992                                        ... goto `LFB`; ...
     993                                        ... goto `LWC`; ...
     994                                        ... goto `LWB`; ...
     995                                  `LWC`: ; } `LWB:` ;
     996                          `LFC:` ; } `LFB:` ;
     997                } else {
     998                        ... goto `LIF`; ...
     999                } `L3:` ;
     1000        } `LS:` ;
     1001} `LC:` ;
     1002\end{cfa}
     1003&
     1004\begin{cfa}
     1005
     1006
     1007
     1008
     1009
     1010
     1011
     1012// terminate compound
     1013// terminate switch
     1014// terminate if
     1015// continue loop
     1016// terminate loop
     1017// continue loop
     1018// terminate loop
     1019
     1020
     1021
     1022// terminate if
     1023
     1024
     1025
     1026\end{cfa}
     1027\end{tabular}
     1028\lstMakeShortInline@%
     1029\caption{Multi-level Exit}
     1030\label{f:MultiLevelExit}
     1031\end{figure}
     1032
     1033Both labelled @continue@ and @break@ are a @goto@ restricted in the following ways:
     1034\begin{itemize}
     1035\item
     1036They cannot create a loop, which means only the looping constructs cause looping.
     1037This restriction means all situations resulting in repeated execution are clearly delineated.
     1038\item
     1039They cannot branch into a control structure.
     1040This restriction prevents missing declarations and/or initializations at the start of a control structure resulting in undefined behaviour.
     1041\end{itemize}
     1042The advantage of the labelled @continue@/@break@ is allowing static multi-level exits without having to use the @goto@ statement, and tying control flow to the target control structure rather than an arbitrary point in a program.
     1043Furthermore, the location of the label at the \emph{beginning} of the target control structure informs the reader (eye candy) that complex control-flow is occurring in the body of the control structure.
     1044With @goto@, the label is at the end of the control structure, which fails to convey this important clue early enough to the reader.
     1045Finally, using an explicit target for the transfer instead of an implicit target allows new constructs to be added or removed without affecting existing constructs.
     1046The implicit targets of the current @continue@ and @break@, \ie the closest enclosing loop or @switch@, change as certain constructs are added or removed.
     1047
     1048\TODO{choose and fallthrough here as well?}
     1049
     1050
     1051\subsection{\texorpdfstring{\LstKeywordStyle{with} Clause / Statement}{with Clause / Statement}}
     1052\label{s:WithClauseStatement}
     1053
     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:
     1055\begin{cfa}
     1056struct S {                                                              $\C{// aggregate}$
     1057        char c;                                                         $\C{// fields}$
     1058        int i;
     1059        double d;
     1060};
     1061S s, as[10];
     1062\end{cfa}
     1063However, routines manipulating aggregates have repeition of the aggregate name to access its containing fields:
     1064\begin{cfa}
     1065void f( S s ) {
     1066        `s.`c; `s.`i; `s.`d;                            $\C{// access containing fields}$
     1067}
     1068\end{cfa}
     1069A similar situation occurs in object-oriented programming, \eg \CC:
     1070\begin{C++}
     1071class C {
     1072        char c;                                                         $\C{// fields}$
     1073        int i;
     1074        double d;
     1075        int mem() {                                                     $\C{// implicit "this" parameter}$
     1076                `this->`c; `this->`i; `this->`d;$\C{// access containing fields}$
     1077        }
     1078}
     1079\end{C++}
     1080Nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of nested lexical-scoping.
     1081
     1082% In object-oriented programming, there is an implicit first parameter, often names @self@ or @this@, which is elided.
     1083% In any programming language, some functions have a naturally close relationship with a particular 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.
     1085% Class methods have certain privileges with respect to their associated data type, notably un-prefixed access to the fields of that data type.
     1086% 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.
     1087%
     1088% \TODO{Fill out section. Be sure to mention arbitrary expressions in with-blocks, recent change driven by Thierry to prioritize field name over parameters.}
     1089
     1090\CFA provides a @with@ clause/statement (see Pascal~\cite[\S~4.F]{Pascal}) to elided aggregate qualification to fields by opening a scope containing field identifiers.
     1091Hence, the qualified fields become variables, and making it easier to optimizing field references in a block.
     1092\begin{cfa}
     1093void f( S s ) `with s` {                                $\C{// with clause}$
     1094        c; i; d;                                                        $\C{\color{red}// s.c, s.i, s.d}$
     1095}
     1096\end{cfa}
     1097and the equivalence for object-style programming is:
     1098\begin{cfa}
     1099int mem( S & this ) `with this` {               $\C{// with clause}$
     1100        c; i; d;                                                        $\C{\color{red}// this.c, this.i, this.d}$
     1101}
     1102\end{cfa}
     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:
     1104\begin{cfa}
     1105struct T { double m, n; };
     1106int mem( S & s, T & t ) `with s, t` {   $\C{// multiple aggregate parameters}$
     1107        c; i; d;                                                        $\C{\color{red}// s.c, s.i, s.d}$
     1108        m; n;                                                           $\C{\color{red}// t.m, t.n}$
     1109}
     1110\end{cfa}
     1111The equivalent object-oriented style is:
     1112\begin{cfa}
     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;
     1116}
     1117\end{cfa}
     1118
     1119The statement form is used within a block:
     1120\begin{cfa}
     1121int foo() {
     1122        struct S1 { ... } s1;
     1123        struct S2 { ... } s2;
     1124        `with s1` {                                             $\C{// with statement}$
     1125                // access fields of s1 without qualification
     1126                `with s2` {                                     $\C{// nesting}$
     1127                        // access fields of s1 and s2 without qualification
     1128                }
     1129        }
     1130        `with s1, s2` {
     1131                // access unambiguous fields of s1 and s2 without qualification
     1132        }
     1133}
     1134\end{cfa}
     1135
     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
     1178
     1179\subsection{Exception Handling ???}
     1180
     1181
     1182\section{Declarations}
     1183
     1184It is important to the design team that \CFA subjectively ``feel like'' C to user programmers.
     1185An important part of this subjective feel is maintaining C's procedural programming paradigm, as opposed to the object-oriented paradigm of other systems languages such as \CC and Rust.
     1186Maintaining this procedural paradigm means that coding patterns that work in C will remain not only functional but idiomatic in \CFA, reducing the mental burden of retraining C programmers and switching between C and \CFA development.
     1187Nonetheless, some features of object-oriented languages are undeniably convienient, and the \CFA design team has attempted to adapt them to a procedural paradigm so as to incorporate their benefits into \CFA; two of these features are resource management and name scoping.
     1188
     1189
     1190\subsection{Alternative Declaration Syntax}
     1191
     1192
     1193\subsection{References}
     1194
     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 @&?@.
     1201
     1202\begin{cfa}
     1203int x = 1, y = 2, * p1, * p2, ** p3;
     1204p1 = &x;  $\C{// p1 points to x}$
     1205p2 = &y;  $\C{// p2 points to y}$
     1206p3 = &p1;  $\C{// p3 points to p1}$
     1207\end{cfa}
     1208
     1209Unfortunately, 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.
     1210It would be desirable to have the compiler figure out how to elide the dereference operators in a complex expression such as @*p2 = ((*p1 + *p2) * (**p3 - *p1)) / (**p3 - 15);@, for both brevity and clarity.
     1211However, 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.
     1212To 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:
     1213
     1214\begin{cfa}
     1215inx x = 1, y = 2, & r1, & r2, && r3;
     1216&r1 = &x;  $\C{// r1 points to x}$
     1217&r2 = &y;  $\C{// r2 points to y}$
     1218&&r3 = &&r1;  $\C{// r3 points to r2}$
     1219r2 = ((r1 + r2) * (r3 - r1)) / (r3 - 15);  $\C{// implicit dereferencing}$
     1220\end{cfa}
     1221
     1222Except for auto-dereferencing by the compiler, this reference example is exactly the same as the previous pointer example.
     1223Hence, a reference behaves like a variable name -- an lvalue expression which is interpreted as a value, but also has the type system track the address of that value.
     1224One way to conceptualize a reference is via a rewrite rule, where the compiler inserts a dereference operator before the reference variable for each reference qualifier in the reference variable declaration, so the previous example implicitly acts like:
     1225
     1226\begin{cfa}
     1227`*`r2 = ((`*`r1 + `*`r2) * (`**`r3 - `*`r1)) / (`**`r3 - 15);
     1228\end{cfa}
     1229
     1230References in \CFA are similar to those in \CC, but with a couple important improvements, both of which can be seen in the example above.
     1231Firstly, \CFA does not forbid references to references, unlike \CC.
     1232This provides a much more orthogonal design for library implementors, obviating the need for workarounds such as @std::reference_wrapper@.
     1233
     1234Secondly, unlike the references in \CC which always point to a fixed address, \CFA references are rebindable.
     1235This allows \CFA references to be default-initialized (to a null pointer), and also to point to different addresses throughout their lifetime.
     1236This rebinding is accomplished without adding any new syntax to \CFA, but simply by extending the existing semantics of the address-of operator in C.
     1237In 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.
     1238In \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.
     1239The result of this rule is that any reference can be rebound using the existing pointer assignment semantics by assigning a compatible pointer into the address of the reference, \eg @&r1 = &x;@ above.
     1240This rebinding can occur to an arbitrary depth of reference nesting; $n$ address-of operators applied to a reference nested $m$ times will produce an lvalue pointer nested $n$ times if $n \le m$ (note that $n = m+1$ is simply the usual C rvalue address-of operator applied to the $n = m$ case).
     1241The explicit address-of operators can be thought of as ``cancelling out'' the implicit dereference operators, \eg @(&`*`)r1 = &x;@ or @(&(&`*`)`*`)r3 = &(&`*`)r1;@ or even @(&`*`)r2 = (&`*`)`*`r3;@ for @&r2 = &r3;@.
     1242
     1243Since 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.
     1244By analogy to pointers, \CFA references also allow cv-qualifiers:
     1245
     1246\begin{cfa}
     1247const int cx = 5;               $\C{// cannot change cx}$
     1248const int & cr = cx;    $\C{// cannot change cr's referred value}$
     1249&cr = &cx;                              $\C{// rebinding cr allowed}$
     1250cr = 7;                                 $\C{// ERROR, cannot change cr}$
     1251int & const rc = x;             $\C{// must be initialized, like in \CC}$
     1252&rc = &x;                               $\C{// ERROR, cannot rebind rc}$
     1253rc = 7;                                 $\C{// x now equal to 7}$
     1254\end{cfa}
     1255
     1256\TODO{Pull more draft text from user manual; make sure to discuss initialization and reference conversions}
     1257
     1258
     1259\subsection{Constructors and Destructors}
     1260
     1261One 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.
     1262However, 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.
     1263\CC is well-known for an approach to manual memory management that addresses both these issues, Resource Allocation Is Initialization (RAII), implemented by means of special \emph{constructor} and \emph{destructor} functions; we have implemented a similar feature in \CFA.
     1264
     1265\TODO{Fill out section. Mention field-constructors and at-equal escape hatch to C-style initialization. Probably pull some text from Rob's thesis for first draft.}
     1266
     1267
     1268\subsection{Default Parameters}
     1269
     1270
     1271\section{Literals}
     1272
     1273
     1274\subsection{0/1}
     1275
     1276\TODO{Some text already at the end of Section~\ref{sec:poly-fns}}
     1277
     1278
     1279\subsection{Units}
     1280
     1281Alternative call syntax (literal argument before routine name) to convert basic literals into user literals.
     1282
     1283{\lstset{language=CFA,deletedelim=**[is][]{`}{`},moredelim=**[is][\color{red}]{@}{@}}
     1284\begin{cfa}
     1285struct Weight { double stones; };
     1286
     1287void ?{}( Weight & w ) { w.stones = 0; } $\C{// operations}$
     1288void ?{}( Weight & w, double w ) { w.stones = w; }
     1289Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; }
     1290
     1291Weight @?`st@( double w ) { return (Weight){ w }; } $\C{// backquote for units}$
     1292Weight @?`lb@( double w ) { return (Weight){ w / 14.0 }; }
     1293Weight @?`kg@( double w ) { return (Weight) { w * 0.1575}; }
     1294
     1295int main() {
     1296        Weight w, hw = { 14 };                  $\C{// 14 stone}$
     1297        w = 11@`st@ + 1@`lb@;
     1298        w = 70.3@`kg@;
     1299        w = 155@`lb@;
     1300        w = 0x_9b_u@`lb@;                               $\C{// hexadecimal unsigned weight (155)}$
     1301        w = 0_233@`lb@;                                 $\C{// octal weight (155)}$
     1302        w = 5@`st@ + 8@`kg@ + 25@`lb@ + hw;
     1303}
     1304\end{cfa}
     1305}%
     1306
     1307
    9041308\section{Evaluation}
    9051309\label{sec:eval}
     
    10131417In contrast, \CFA has a single facility for polymorphic code supporting type-safe separate-compilation of polymorphic functions and generic (opaque) types, which uniformly leverage the C procedural paradigm.
    10141418The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed properties for a type.
    1015 Until \CC~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function in code beyond compilation errors during template expansion;
     1419Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function in code beyond compilation errors during template expansion;
    10161420furthermore, \CC concepts are restricted to template polymorphism.
    10171421
     
    10211425In \CFA terms, all Cyclone polymorphism must be dtype-static.
    10221426While the Cyclone design provides the efficiency benefits discussed in Section~\ref{sec:generic-apps} for dtype-static polymorphism, it is more restrictive than \CFA's general model.
    1023 \cite{Smith98} present Polymorphic C, an ML dialect with polymorphic functions and C-like syntax and pointer types; it lacks many of C's features, however, most notably structure types, and so is not a practical C replacement.
    1024 
    1025 \cite{obj-c-book} is an industrially successful extension to C.
     1427Smith and Volpano~\cite{Smith98} present Polymorphic C, an ML dialect with polymorphic functions, C-like syntax, and pointer types; it lacks many of C's features, however, most notably structure types, and so is not a practical C replacement.
     1428
     1429Objective-C~\cite{obj-c-book} is an industrially successful extension to C.
    10261430However, Objective-C is a radical departure from C, using an object-oriented model with message-passing.
    10271431Objective-C did not support type-checked generics until recently \cite{xcode7}, historically using less-efficient runtime checking of object types.
    1028 The~\cite{GObject} framework also adds object-oriented programming with runtime type-checking and reference-counting garbage-collection to C;
     1432The GObject~\cite{GObject} framework also adds object-oriented programming with runtime type-checking and reference-counting garbage-collection to C;
    10291433these features are more intrusive additions than those provided by \CFA, in addition to the runtime overhead of reference-counting.
    1030 \cite{Vala} compiles to GObject-based C, adding the burden of learning a separate language syntax to the aforementioned demerits of GObject as a modernization path for existing C code-bases.
     1434Vala~\cite{Vala} compiles to GObject-based C, adding the burden of learning a separate language syntax to the aforementioned demerits of GObject as a modernization path for existing C code-bases.
    10311435Java~\cite{Java8} included generic types in Java~5, which are type-checked at compilation and type-erased at runtime, similar to \CFA's.
    10321436However, in Java, each object carries its own table of method pointers, while \CFA passes the method pointers separately to maintain a C-compatible layout.
    10331437Java is also a garbage-collected, object-oriented language, with the associated resource usage and C-interoperability burdens.
    10341438
    1035 D~\cite{D}, Go, and~\cite{Rust} are modern, compiled languages with abstraction features similar to \CFA traits, \emph{interfaces} in D and Go and \emph{traits} in Rust.
     1439D~\cite{D}, Go, and Rust~\cite{Rust} are modern, compiled languages with abstraction features similar to \CFA traits, \emph{interfaces} in D and Go and \emph{traits} in Rust.
    10361440However, each language represents a significant departure from C in terms of language model, and none has the same level of compatibility with C as \CFA.
    10371441D and Go are garbage-collected languages, imposing the associated runtime overhead.
     
    10541458\CCeleven introduced @std::tuple@ as a library variadic template structure.
    10551459Tuples are a generalization of @std::pair@, in that they allow for arbitrary length, fixed-size aggregation of heterogeneous values.
    1056 Operations include @std::get<N>@ to extract vales, @std::tie@ to create a tuple of references used for assignment, and lexicographic comparisons.
     1460Operations include @std::get<N>@ to extract values, @std::tie@ to create a tuple of references used for assignment, and lexicographic comparisons.
    10571461\CCseventeen proposes \emph{structured bindings}~\cite{Sutter15} to eliminate pre-declaring variables and use of @std::tie@ for binding the results.
    10581462This extension requires the use of @auto@ to infer the types of the new variables, so complicated expressions with a non-obvious type must be documented with some other mechanism.
     
    10681472The goal of \CFA is to provide an evolutionary pathway for large C development-environments to be more productive and safer, while respecting the talent and skill of C programmers.
    10691473While other programming languages purport to be a better C, they are in fact new and interesting languages in their own right, but not C extensions.
    1070 The purpose of this paper is to introduce \CFA, and showcase two language features that illustrate the \CFA type-system and approaches taken to achieve the goal of evolutionary C extension.
     1474The purpose of this paper is to introduce \CFA, and showcase language features that illustrate the \CFA type-system and approaches taken to achieve the goal of evolutionary C extension.
    10711475The contributions are a powerful type-system using parametric polymorphism and overloading, generic types, and tuples, which all have complex interactions.
    10721476The work is a challenging design, engineering, and implementation exercise.
  • src/Common/PassVisitor.impl.h

    r7323573 r5f95b5f  
    998998template< typename pass_type >
    999999void PassVisitor< pass_type >::visit( FinallyStmt * node ) {
    1000         VISIT_BODY( node );
     1000        VISIT_START( node );
     1001
     1002        maybeAccept_impl( node->block, *this );
     1003
     1004        VISIT_END( node );
    10011005}
    10021006
    10031007template< typename pass_type >
    10041008Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
    1005         MUTATE_BODY( Statement, node );
     1009        MUTATE_START( node );
     1010
     1011        maybeMutate_impl( node->block, *this );
     1012
     1013        MUTATE_END( Statement, node );
    10061014}
    10071015
  • src/GenPoly/Box.cc

    r7323573 r5f95b5f  
    988988
    989989                Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
    990                         if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->get_function() ) ) {
    991                                 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
    992                                         if ( varExpr->get_var()->get_name() == "?[?]" ) {
     990                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->function ) ) {
     991                                if ( varExpr->var->linkage == LinkageSpec::Intrinsic ) {
     992                                        if ( varExpr->var->name == "?[?]" ) {
    993993                                                assert( appExpr->result );
    994994                                                assert( appExpr->get_args().size() == 2 );
    995                                                 Type *baseType1 = isPolyPtr( appExpr->get_args().front()->get_result(), scopeTyVars, env );
    996                                                 Type *baseType2 = isPolyPtr( appExpr->get_args().back()->get_result(), scopeTyVars, env );
     995                                                Type *baseType1 = isPolyPtr( appExpr->args.front()->result, scopeTyVars, env );
     996                                                Type *baseType2 = isPolyPtr( appExpr->args.back()->result, scopeTyVars, env );
    997997                                                assert( ! baseType1 || ! baseType2 ); // the arguments cannot both be polymorphic pointers
    998998                                                UntypedExpr *ret = 0;
     
    15551555                        // only mutate member expressions for polymorphic types
    15561556                        int tyDepth;
    1557                         Type *objectType = hasPolyBase( memberExpr->get_aggregate()->get_result(), scopeTyVars, &tyDepth );
     1557                        Type *objectType = hasPolyBase( memberExpr->aggregate->result, scopeTyVars, &tyDepth );
    15581558                        if ( ! objectType ) return memberExpr;
    15591559                        findGeneric( objectType ); // ensure layout for this type is available
    15601560
    15611561                        // replace member expression with dynamically-computed layout expression
    1562                         Expression *newMemberExpr = 0;
     1562                        Expression *newMemberExpr = nullptr;
    15631563                        if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
    15641564                                // look up offset index
    1565                                 long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
     1565                                long i = findMember( memberExpr->member, structType->baseStruct->members );
    15661566                                if ( i == -1 ) return memberExpr;
    15671567
    15681568                                // replace member expression with pointer to base plus offset
    15691569                                UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
    1570                                 Expression * aggr = memberExpr->get_aggregate()->clone();
    1571                                 delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
    1572                                 aggr->set_env( nullptr );
     1570                                Expression * aggr = memberExpr->aggregate->clone();
     1571                                delete aggr->env; // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
     1572                                aggr->env = nullptr;
    15731573                                fieldLoc->get_args().push_back( aggr );
    15741574                                fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
    1575                                 fieldLoc->set_result( memberExpr->get_result()->clone() );
     1575                                fieldLoc->set_result( memberExpr->result->clone() );
    15761576                                newMemberExpr = fieldLoc;
    15771577                        } else if ( dynamic_cast< UnionInstType* >( objectType ) ) {
    15781578                                // union members are all at offset zero, so just use the aggregate expr
    1579                                 Expression * aggr = memberExpr->get_aggregate()->clone();
    1580                                 delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
    1581                                 aggr->set_env( nullptr );
     1579                                Expression * aggr = memberExpr->aggregate->clone();
     1580                                delete aggr->env; // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it
     1581                                aggr->env= nullptr;
    15821582                                newMemberExpr = aggr;
    1583                                 newMemberExpr->set_result( memberExpr->get_result()->clone() );
     1583                                newMemberExpr->result = memberExpr->result->clone();
    15841584                        } else return memberExpr;
    15851585                        assert( newMemberExpr );
    15861586
    1587                         Type *memberType = memberExpr->get_member()->get_type();
     1587                        Type *memberType = memberExpr->member->get_type();
    15881588                        if ( ! isPolyType( memberType, scopeTyVars ) ) {
    15891589                                // Not all members of a polymorphic type are themselves of polymorphic type; in this case the member expression should be wrapped and dereferenced to form an lvalue
     
    15981598
    15991599                ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
    1600                         ObjectDecl *newObj = new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, 0, type, init );
     1600                        ObjectDecl *newObj = new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, nullptr, type, init );
    16011601                        stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
    16021602                        return newObj;
  • src/GenPoly/InstantiateGeneric.cc

    r7323573 r5f95b5f  
    476476                        DeclarationWithType * field = strict_dynamic_cast< DeclarationWithType * >( member );
    477477                        MemberExpr * ret = new MemberExpr( field, memberExpr->aggregate->clone() );
     478                        ResolvExpr::adjustExprType( ret->result ); // pointer decay
    478479                        std::swap( ret->env, memberExpr->env );
    479480                        delete memberExpr;
  • src/ResolvExpr/AdjustExprType.cc

    r7323573 r5f95b5f  
    2424        class AdjustExprType : public WithShortCircuiting {
    2525          public:
    26                 AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer );
     26                AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer );
    2727                void premutate( VoidType * ) { visit_children = false; }
    2828                void premutate( BasicType * ) { visit_children = false; }
     
    4545
    4646          private:
    47                 const TypeEnvironment &env;
    48                 const SymTab::Indexer &indexer;
     47                const TypeEnvironment & env;
     48                const SymTab::Indexer & indexer;
    4949        };
    5050
     
    5353                Type *newType = type->acceptMutator( adjuster );
    5454                type = newType;
     55        }
     56
     57        void adjustExprType( Type *& type ) {
     58                TypeEnvironment env;
     59                SymTab::Indexer indexer;
     60                adjustExprType( type, env, indexer );
    5561        }
    5662
  • src/ResolvExpr/Resolver.cc

    r7323573 r5f95b5f  
    280280                        std::list< Statement * > newStmts;
    281281                        resolveWithExprs( functionDecl->withExprs, newStmts );
    282                         functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
     282                        if ( functionDecl->statements ) {
     283                                functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
     284                        } else {
     285                                assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
     286                        }
    283287                }
    284288        }
  • src/ResolvExpr/typeops.h

    r7323573 r5f95b5f  
    5555        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
    5656        void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     57
     58        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
     59        void adjustExprType( Type *& type );
    5760
    5861        template< typename ForwardIterator >
  • src/driver/cfa.cc

    r7323573 r5f95b5f  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  1 22:26:10 2018
    13 // Update Count     : 163
     12// Last Modified On : Mon Feb  5 22:05:28 2018
     13// Update Count     : 166
    1414//
    1515
     
    258258                #endif
    259259
     260                args[nargs] = "-Xlinker";
     261                nargs += 1;
     262                args[nargs] = "--undefined=__cfaabi_dbg_bits_write";
     263                nargs += 1;
     264                args[nargs] = "-Xlinker";
     265                nargs += 1;
     266                args[nargs] = "--undefined=__cfaabi_interpose_startup";
     267                nargs += 1;
     268
    260269                // include the cfa library in case it's needed
    261270                args[nargs] = "-L" CFA_LIBDIR;
     
    273282                args[nargs] = "-lrt";
    274283                nargs += 1;
    275                 args[nargs] = "-Xlinker";
    276                 nargs += 1;
    277                 args[nargs] = "--undefined=__cfaabi_dbg_bits_write";
    278                 nargs += 1;
    279                 args[nargs] = "-Xlinker";
    280                 nargs += 1;
    281                 args[nargs] = "--undefined=__cfaabi_interpose_startup";
    282                 nargs += 1;
    283 
    284         } // if
    285 #endif //HAVE_LIBCFA
     284        } // if
     285#endif // HAVE_LIBCFA
    286286
    287287        // Add exception flags (unconditionally)
     
    333333                nargs += 1;
    334334        } // if
     335
     336    args[nargs] = "-Xlinker";                                                   // used by backtrace
     337    nargs += 1;
     338    args[nargs] = "-export-dynamic";
     339    nargs += 1;
    335340
    336341        // execute the compilation command
  • src/libcfa/interpose.c

    r7323573 r5f95b5f  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 22:27:33 2017
    13 // Update Count     : 1
     12// Last Modified On : Mon Feb  5 23:40:04 2018
     13// Update Count     : 17
    1414//
    1515
     
    3232#include "bits/signal.h"
    3333#include "startup.h"
    34 
    35 void __cfaabi_interpose_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
    3634
    3735typedef void (*generic_fptr_t)(void);
     
    9290void sigHandler_abort( __CFA_SIGPARMS__ );
    9391
    94 void __cfaabi_interpose_startup() {
    95         const char *version = NULL;
    96 
    97         INIT_REALRTN( abort, version );
    98         INIT_REALRTN( exit, version );
    99 
    100         __kernel_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO );      // Failure handler
    101         __kernel_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO );      // Failure handler
    102         __kernel_sigaction( SIGABRT, sigHandler_abort, SA_SIGINFO );      // Failure handler
     92extern "C" {
     93        void __cfaabi_interpose_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
     94        void __cfaabi_interpose_startup( void ) {
     95                const char *version = NULL;
     96
     97                INIT_REALRTN( abort, version );
     98                INIT_REALRTN( exit, version );
     99
     100                __kernel_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO ); // Failure handler
     101                __kernel_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO ); // Failure handler
     102                __kernel_sigaction( SIGABRT, sigHandler_abort, SA_SIGINFO ); // Failure handler
     103        }
    103104}
    104105
     
    108109
    109110extern "C" {
    110         void abort (void) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
     111        void abort( void ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
    111112                abortf( NULL );
    112113        }
    113114
    114         void exit (int __status) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
     115        void exit( int __status ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
    115116                libc_exit(__status);
    116117        }
     
    121122}
    122123
    123 void * kernel_abort    (void) __attribute__ ((__nothrow__, __leaf__, __weak__)) { return NULL; }
    124 void   kernel_abort_msg(void * data, char * buffer, int size) __attribute__ ((__nothrow__, __leaf__, __weak__)) {}
     124void * kernel_abort    ( void ) __attribute__ ((__nothrow__, __leaf__, __weak__)) { return NULL; }
     125void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__ ((__nothrow__, __leaf__, __weak__)) {}
    125126
    126127enum { abort_text_size = 1024 };
     
    133134                int len;
    134135
    135                 if( fmt ) {
     136                if ( fmt ) {
    136137                        va_list args;
    137138                        va_start( args, fmt );
     
    142143
    143144                        __cfaabi_dbg_bits_write( abort_text, len );
    144                         __cfaabi_dbg_bits_write( "\n", 1 );
     145                        //__cfaabi_dbg_bits_write( "\n", 1 );
    145146                }
    146147
     
    162163        enum { Frames = 50 };
    163164        void * array[Frames];
    164         int size = backtrace( array, Frames );
     165        size_t size = backtrace( array, Frames );
    165166        char ** messages = backtrace_symbols( array, size );
    166167
     
    176177
    177178                for ( char *p = messages[i]; *p; ++p ) {
     179                        //__cfaabi_dbg_bits_print_nolock( "X %s\n", p);
    178180                        // find parantheses and +offset
    179181                        if ( *p == '(' ) {
Note: See TracChangeset for help on using the changeset viewer.