Changeset 8614140 for doc/theses/mike_brooks_MMath/array.tex
- Timestamp:
- Jan 8, 2026, 1:26:42 PM (4 weeks ago)
- Branches:
- master
- Children:
- fb7c9168
- Parents:
- 79ba50c (diff), 4904b05 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
doc/theses/mike_brooks_MMath/array.tex (modified) (53 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/mike_brooks_MMath/array.tex
r79ba50c r8614140 2 2 \label{c:Array} 3 3 4 Arrays in C are possibly the single most misunderstood and incorrectly used feature in the language , resulting in the largest proportion of runtime errors and security violations.4 Arrays in C are possibly the single most misunderstood and incorrectly used feature in the language \see{\VRef{s:Array}}, resulting in the largest proportion of runtime errors and security violations. 5 5 This chapter describes the new \CFA language and library features that introduce a length-checked array type, @array@, to the \CFA standard library~\cite{Cforall}. 6 6 … … 13 13 \label{s:ArrayIntro} 14 14 15 The new \CFA array is declared by instantiating the generic @array@ type, 16 much like instantiating any other standard-library generic type (such as \CC @vector@), 17 though using a new style of generic parameter. 15 The new \CFA array is declared by instantiating the generic @array@ type, much like instantiating any other standard-library generic type (such as \CC @vector@), using a new style of generic parameter. 18 16 \begin{cfa} 19 17 @array( float, 99 )@ x; $\C[2.5in]{// x contains 99 floats}$ … … 24 22 void f( @array( float, 42 )@ & p ) {} $\C{// p accepts 42 floats}$ 25 23 f( x ); $\C{// statically rejected: type lengths are different, 99 != 42}$ 24 26 25 test2.cfa:3:1 error: Invalid application of existing declaration(s) in expression. 27 26 Applying untyped: Name: f ... to: Name: x … … 37 36 g( x, 0 ); $\C{// T is float, N is 99, dynamic subscript check succeeds}$ 38 37 g( x, 1000 ); $\C{// T is float, N is 99, dynamic subscript check fails}$ 38 39 39 Cforall Runtime error: subscript 1000 exceeds dimension range [0,99) $for$ array 0x555555558020. 40 40 \end{cfa} … … 92 92 is a sufficient postcondition. 93 93 In an imperative language like C and \CFA, it is also necessary to discuss side effects, for which an even heavier formalism, like separation logic, is required. 94 Secondly , TODO:bash Rust.95 % TODO:cite the crap out of these claims.94 Secondly: ... bash Rust. 95 ... cite the crap out of these claims. 96 96 \end{comment} 97 97 … … 110 110 forall( T & | sized(T) ) 111 111 T * alloc() { 112 return @(T *)@malloc( @sizeof(T)@ ); 112 return @(T *)@malloc( @sizeof(T)@ ); // C malloc 113 113 } 114 114 \end{cfa} … … 132 132 The loops follow the familiar pattern of using the variable @dim@ to iterate through the arrays. 133 133 Most importantly, the type system implicitly captures @dim@ at the call of @f@ and makes it available throughout @f@ as @N@. 134 The example shows @dim@ adapting into a type-system managed length at the declarations of @x@, @y@, and @result@ , @N@ adapting in the same way at @f@'s loop bound,and a pass-thru use of @dim@ at @f@'s declaration of @ret@.134 The example shows @dim@ adapting into a type-system managed length at the declarations of @x@, @y@, and @result@; @N@ adapting in the same way at @f@'s loop bound; and a pass-thru use of @dim@ at @f@'s declaration of @ret@. 135 135 Except for the lifetime-management issue of @result@, \ie explicit @free@, this program has eliminated both the syntactic and semantic problems associated with C arrays and their usage. 136 136 The result is a significant improvement in safety and usability. … … 148 148 \end{itemize} 149 149 150 \VRef[Figure]{f:TemplateVsGenericType} shows @N@ is not the same as a @size_t@ declaration in a \CC \lstinline[language=C++]{template}. 150 \VRef[Figure]{f:TemplateVsGenericType} shows @N@ is not the same as a @size_t@ declaration in a \CC \lstinline[language=C++]{template}.\footnote{ 151 The \CFA program requires a snapshot declaration for \lstinline{n} to compile, as described at the end of \Vref{s:ArrayTypingC}.} 151 152 \begin{enumerate}[leftmargin=*] 152 153 \item 153 154 The \CC template @N@ can only be a compile-time value, while the \CFA @N@ may be a runtime value. 154 155 \item 155 \CC does not allow a template function to be nested, while \CFA lets its polymorphic functions tobe nested.156 \CC does not allow a template function to be nested, while \CFA allows polymorphic functions be nested. 156 157 Hence, \CC precludes a simple form of information hiding. 157 158 \item … … 176 177 % mycode/arrr/thesis-examples/check-peter/cs-cpp.cpp, v10 177 178 \end{enumerate} 178 The \CC template @array@ type mitigates points \VRef[]{p:DimensionPassing} and \VRef[]{p:ArrayCopy}, but it is also trying to accomplish a similar mechanism to \CFA @array@. 179 The \CC template @std::array@ tries to accomplish a similar mechanism to \CFA @array@. 180 It is an aggregate type with the same semantics as a @struct@ holding a C-style array \see{\VRef{s:ArraysCouldbeValues}}, which mitigates points \VRef[]{p:DimensionPassing} and \VRef[]{p:ArrayCopy}. 179 181 180 182 \begin{figure} 181 \begin{tabular}{@{}l @{\hspace{20pt}}l@{}}183 \begin{tabular}{@{}ll@{}} 182 184 \begin{c++} 183 185 … … 187 189 } 188 190 int main() { 189 190 int ret[ 10], x[10];191 for ( int i = 0; i < 10; i += 1 ) x[i] = i;192 @copy<int, 10>( ret, x );@193 for ( int i = 0; i < 10; i += 1 )191 const size_t n = 10; // must be constant 192 int ret[n], x[n]; 193 for ( int i = 0; i < n; i += 1 ) x[i] = i; 194 @copy<int, n >( ret, x );@ 195 for ( int i = 0; i < n; i += 1 ) 194 196 cout << ret[i] << ' '; 195 197 cout << endl; … … 203 205 for ( i; N ) ret[i] = x[i]; 204 206 } 205 206 const int n = promptForLength();207 size_t n; 208 sin | n; 207 209 array( int, n ) ret, x; 208 210 for ( i; n ) x[i] = i; … … 228 230 When the argument lengths themselves are statically unknown, 229 231 the static check is conservative and, as always, \CFA's casting lets the programmer use knowledge not shared with the type system. 230 \begin{tabular}{@{\hspace{0.5in}}l@{\hspace{1in}}l@{}} 231 \lstinput{90-97}{hello-array.cfa} 232 & 233 \lstinput{110-117}{hello-array.cfa} 234 \end{tabular} 235 236 \noindent 237 This static check's full rules are presented in \VRef[Section]{s:ArrayTypingC}. 232 \lstinput{90-96}{hello-array.cfa} 233 This static check's rules are presented in \VRef[Section]{s:ArrayTypingC}. 238 234 239 235 Orthogonally, the \CFA array type works within generic \emph{types}, \ie @forall@-on-@struct@. 240 236 The same argument safety and the associated implicit communication of array length occurs. 241 237 Preexisting \CFA allowed aggregate types to be generalized with type parameters, enabling parameterizing of element types. 242 This has beenextended to allow parameterizing by dimension.243 Doing so gives a refinement of C's ``flexible array member''~\cite[\S~6.7.2.1.18]{C11} .238 This feature is extended to allow parameterizing by dimension. 239 Doing so gives a refinement of C's ``flexible array member''~\cite[\S~6.7.2.1.18]{C11}: 244 240 \begin{cfa} 245 241 struct S { … … 264 260 \end{cfa} 265 261 This ability to avoid casting and size arithmetic improves safety and usability over C flexible array members. 266 Finally, inputs and outputs are given at the bottomfor different sized schools.262 Finally, inputs and outputs are given on the right for different sized schools. 267 263 The example program prints the courses in each student's preferred order, all using the looked-up display names. 268 264 269 265 \begin{figure} 270 \begin{cquote} 271 \lstinput{50-55}{hello-accordion.cfa} 266 \begin{lrbox}{\myboxA} 267 \begin{tabular}{@{}l@{}} 268 \lstinput{50-55}{hello-accordion.cfa} \\ 272 269 \lstinput{90-98}{hello-accordion.cfa} 273 \ \\ 274 @$ cat school1@ 275 \lstinput{}{school1} 276 277 @$ ./a.out < school1@ 278 \lstinput{}{school1.out} 279 280 @$ cat school2@ 281 \lstinput{}{school2} 282 283 @$ ./a.out < school2@ 284 \lstinput{}{school2.out} 285 \end{cquote} 270 \end{tabular} 271 \end{lrbox} 272 273 \begin{lrbox}{\myboxB} 274 \begin{tabular}{@{}l@{}} 275 @$ cat school1@ \\ 276 \lstinputlisting{school1} \\ 277 @$ ./a.out < school1@ \\ 278 \lstinputlisting{school1.out} \\ 279 @$ cat school2@ \\ 280 \lstinputlisting{school2} \\ 281 @$ ./a.out < school2@ \\ 282 \lstinputlisting{school2.out} 283 \end{tabular} 284 \end{lrbox} 285 286 \setlength{\tabcolsep}{10pt} 287 \begin{tabular}{@{}ll@{}} 288 \usebox\myboxA 289 & 290 \usebox\myboxB 291 \end{tabular} 286 292 287 293 \caption{\lstinline{School} Example, Input and Output} … … 290 296 291 297 When a function operates on a @School@ structure, the type system handles its memory layout transparently. 292 \lstinput{30-3 7}{hello-accordion.cfa}298 \lstinput{30-36}{hello-accordion.cfa} 293 299 In the example, function @getPref@ returns, for the student at position @is@, what is the position of their @pref@\textsuperscript{th}-favoured class? 294 300 … … 296 302 \section{Dimension Parameter Implementation} 297 303 298 The core of the preexisting \CFA compiler already ha dthe ``heavy equipment'' needed to provide the feature set just reviewed (up to bugs in cases not yet exercised).304 The core of the preexisting \CFA compiler already has the ``heavy equipment'' needed to provide the feature set just reviewed (up to bugs in cases not yet exercised). 299 305 To apply this equipment in tracking array lengths, I encoded a dimension (array's length) as a type. 300 306 The type in question does not describe any data that the program actually uses at runtime. … … 323 329 \begin{itemize}[leftmargin=*] 324 330 \item 325 Resolver provided values for a useddeclaration's type-system variables, gathered from type information in scope at the usage site.326 \item 327 The box pass, encoding information about type parameters into ``extra'' regular parameters /arguments on declarations and calls.331 Resolver provided values for a declaration's type-system variables, gathered from type information in scope at the usage site. 332 \item 333 The box pass, encoding information about type parameters into ``extra'' regular parameters and arguments on declarations and calls. 328 334 Notably, it conveys the size of a type @foo@ as a @__sizeof_foo@ parameter, and rewrites the @sizeof(foo)@ expression as @__sizeof_foo@, \ie a use of the parameter. 329 335 \end{itemize} … … 331 337 The rules for resolution had to be restricted slightly, in order to achieve important refusal cases. 332 338 This work is detailed in \VRef[Section]{s:ArrayTypingC}. 333 However, the resolution--boxing scheme, in its preexisting state, was alreadyequipped to work on (desugared) dimension parameters.339 However, the resolution--boxing scheme, in its preexisting state, is equipped to work on (desugared) dimension parameters. 334 340 The following discussion explains the desugaring and how correctly lowered code results. 335 341 … … 357 363 \end{enumerate} 358 364 The chosen solution is to encode the value @N@ \emph{as a type}, so items 1 and 2 are immediately available for free. 359 Item 3 needs a way to recover the encoded value from a (valid) type (and to reject invalid types occurring here).365 Item 3 needs a way to recover the encoded value from a (valid) type and to reject invalid types. 360 366 Item 4 needs a way to produce a type that encodes the given value. 361 367 … … 416 422 The type @thing(N)@ is (replaced by @void *@, but thereby effectively) gone. 417 423 \item 418 The @sout...@ expression (being an application of the @?|?@ operator)has a regular variable (parameter) usage for its second argument.424 The @sout...@ expression has a regular variable (parameter) usage for its second argument. 419 425 \item 420 426 Information about the particular @thing@ instantiation (value 10) is moved, from the type, to a regular function-call argument. … … 455 461 \begin{cfa} 456 462 enum { n = 42 }; 457 float x[@n@]; // or just 42458 float (*xp1)[@42@] = &x; // accept459 float (*xp2)[@999@] = &x; // reject463 float x[@n@]; $\C{// or just 42}$ 464 float (*xp1)[@42@] = &x; $\C{// accept}$ 465 float (*xp2)[@999@] = &x; $\C{// reject}$ 460 466 warning: initialization of 'float (*)[999]' from incompatible pointer type 'float (*)[42]' 461 467 \end{cfa} 462 468 When a variable is involved, C and \CFA take two different approaches. 463 Today's C compilers accept the following without warning.469 Today's C compilers accept the following without a warning. 464 470 \begin{cfa} 465 471 static const int n = 42; … … 482 488 The way the \CFA array is implemented, the type analysis for this case reduces to a case similar to the earlier C version. 483 489 The \CFA compiler's compatibility analysis proceeds as: 484 \begin{itemize}[ parsep=0pt]490 \begin{itemize}[leftmargin=*,parsep=0pt] 485 491 \item 486 492 Is @array( float, 999 )@ type-compatible with @array( float, n )@? … … 510 516 in order to preserve the length information that powers runtime bound-checking.} 511 517 Therefore, the need to upgrade legacy C code is low. 512 Finally, if this incompatibility is a problem onboarding C programs to \CFA, it isshould be possible to change the C type check to a warning rather than an error, acting as a \emph{lint} of the original code for a missing type annotation.518 Finally, if this incompatibility is a problem onboarding C programs to \CFA, it should be possible to change the C type check to a warning rather than an error, acting as a \emph{lint} of the original code for a missing type annotation. 513 519 514 520 To handle two occurrences of the same variable, more information is needed, \eg, this is fine, … … 516 522 int n = 42; 517 523 float x[@n@]; 518 float (*xp)[@n@] = x; // accept524 float (*xp)[@n@] = x; $\C{// accept}$ 519 525 \end{cfa} 520 526 where @n@ remains fixed across a contiguous declaration context. 521 However, intervening dynamic statement cause failures.527 However, intervening dynamic statements can cause failures. 522 528 \begin{cfa} 523 529 int n = 42; 524 530 float x[@n@]; 525 @n@ = 999; // dynamic change526 float (*xp)[@n@] = x; // reject527 \end{cfa} 528 However, side-effects can occur in a contiguous declaration context.531 @n@ = 999; $\C{// dynamic change}$ 532 float (*xp)[@n@] = x; $\C{// reject}$ 533 \end{cfa} 534 As well, side-effects can even occur in a contiguous declaration context. 529 535 \begin{cquote} 530 536 \setlength{\tabcolsep}{20pt} … … 536 542 void f() { 537 543 float x[@n@] = { g() }; 538 float (*xp)[@n@] = x; // reject544 float (*xp)[@n@] = x; // reject 539 545 } 540 546 \end{cfa} … … 544 550 int @n@ = 42; 545 551 void g() { 546 @n@ = 99 ;552 @n@ = 999; // accept 547 553 } 548 554 … … 553 559 The issue here is that knowledge needed to make a correct decision is hidden by separate compilation. 554 560 Even within a translation unit, static analysis might not be able to provide all the information. 555 However, if the example uses @const@, the check is possible .561 However, if the example uses @const@, the check is possible even though the value is unknown. 556 562 \begin{cquote} 557 563 \setlength{\tabcolsep}{20pt} … … 563 569 void f() { 564 570 float x[n] = { g() }; 565 float (*xp)[n] = x; // reject571 float (*xp)[n] = x; // accept 566 572 } 567 573 \end{cfa} … … 571 577 @const@ int n = 42; 572 578 void g() { 573 @n = 99 @; // allowed579 @n = 999@; // reject 574 580 } 575 581 … … 692 698 An expression-compatibility question is a new addition to the \CFA compiler, and occurs in the context of dimension expressions, and possibly enumerations assigns, which must be unique. 693 699 694 % TODO:ensure these compiler implementation matters are treated under \CFA compiler background: type unification, cost calculation, GenPoly.700 % ... ensure these compiler implementation matters are treated under \CFA compiler background: type unification, cost calculation, GenPoly. 695 701 696 702 The relevant technical component of the \CFA compiler is the standard type-unification within the type resolver. … … 726 732 \end{cfa} 727 733 when resolving a function call to @g@, the first unification stage compares the type @T@ of the parameter with @array( float, n + 1 )@, of the argument. 728 \PAB{TODO: finish.}729 734 730 735 The actual rules for comparing two dimension expressions are conservative. … … 732 737 is to imply, ``all else being equal, allow an array with length calculated by $e_1$ 733 738 to be passed to a function expecting a length-$e_2$ array.''\footnote{ 734 TODO:Deal with directionality, that I'm doing exact-match, no ``at least as long as,'' no subtyping.739 ... Deal with directionality, that I'm doing exact-match, no ``at least as long as,'' no subtyping. 735 740 Should it be an earlier scoping principle? Feels like it should matter in more places than here.} 736 741 So, a ``yes'' answer must represent a guarantee that both expressions evaluate the … … 746 751 So, a variable and a literal can never match. 747 752 748 TODO:Discuss the interaction of this dimension hoisting with the challenge of extra unification for cost calculation753 ... Discuss the interaction of this dimension hoisting with the challenge of extra unification for cost calculation 749 754 \end{comment} 750 755 751 The conservatism of the new rule set can leave a programmer needing a recourse, when needing to use a dimension expression whose stability argument is more subtle than current-state analysis.756 The conservatism of the new rule set can leave a programmer requiring a recourse, when needing to use a dimension expression whose stability argument is more subtle than current-state analysis. 752 757 This recourse is to declare an explicit constant for the dimension value. 753 758 Consider these two dimension expressions, whose uses are rejected by the blunt current-state rules: … … 755 760 void f( int @&@ nr, @const@ int nv ) { 756 761 float x[@nr@]; 757 float (*xp)[@nr@] = &x; // reject: nr varying (no references)762 float (*xp)[@nr@] = &x; // reject: nr varying (no references) 758 763 float y[@nv + 1@]; 759 float (*yp)[@nv + 1@] = &y; // reject: ?+? unpredictable (no functions)764 float (*yp)[@nv + 1@] = &y; // reject: ?+? unpredictable (no functions) 760 765 } 761 766 \end{cfa} 762 767 Yet, both dimension expressions are reused safely. 763 The @nr@ reference is never written, no t volatile meaning noimplicit code (load) between declarations, and control does not leave the function between the uses.768 The @nr@ reference is never written, no implicit code (load) between declarations, and control does not leave the function between the uses. 764 769 As well, the build-in @?+?@ function is predictable. 765 770 To make these cases work, the programmer must add the follow constant declarations (cast does not work): … … 768 773 @const int nx@ = nr; 769 774 float x[nx]; 770 float (*xp)[nx] = & x; // accept775 float (*xp)[nx] = & x; // accept 771 776 @const int ny@ = nv + 1; 772 777 float y[ny]; 773 float (*yp)[ny] = & y; // accept778 float (*yp)[ny] = & y; // accept 774 779 } 775 780 \end{cfa} … … 808 813 \end{cfa} 809 814 Dimension hoisting already existed in the \CFA compiler. 810 But itswas buggy, particularly with determining, ``Can hoisting the expression be skipped here?'', for skipping this hoisting is clearly desirable in some cases.815 However, it was buggy, particularly with determining, ``Can hoisting the expression be skipped here?'', for skipping this hoisting is clearly desirable in some cases. 811 816 For example, when a programmer has already hoisted to perform an optimization to prelude duplicate code (expression) and/or expression evaluation. 812 817 In the new implementation, these cases are correct, harmonized with the accept/reject criteria. … … 820 825 \item 821 826 Flexible-stride memory: 822 this model has complete independence between subscript ing ordering and memory layout, offering the ability to slice by (provide an index for) any dimension, \eg slice a plane, row, or column, \eg @c[3][*][*]@, @c[3][4][*]@, @c[3][*][5]@.827 this model has complete independence between subscript ordering and memory layout, offering the ability to slice by (provide an index for) any dimension, \eg slice a row, column, or plane, \eg @c[3][4][*]@, @c[3][*][5]@, @c[3][*][*]@. 823 828 \item 824 829 Fixed-stride memory: … … 839 844 Style 3 is the inevitable target of any array implementation. 840 845 The hardware offers this model to the C compiler, with bytes as the unit of displacement. 841 C offers this model to its programmeras pointer arithmetic, with arbitrary sizes as the unit.846 C offers this model to programmers as pointer arithmetic, with arbitrary sizes as the unit. 842 847 Casting a multidimensional array as a single-dimensional array/pointer, then using @x[i]@ syntax to access its elements, is still a form of pointer arithmetic. 843 848 844 Now stepping into the implementation of \CFA's new type-1 multidimensional arrays in terms of C's existing type-2 multidimensional arrays, it helps to clarify that even the interface is quite low-level. 845 A C/\CFA array interface includes the resulting memory layout. 846 The defining requirement of a type-2 system is the ability to slice a column from a column-finest matrix. 847 The required memory shape of such a slice is fixed, before any discussion of implementation. 848 The implementation presented here is how the \CFA array-library wrangles the C type system, to make it do memory steps that are consistent with this layout while not affecting legacy C programs. 849 To step into the implementation of \CFA's new type-1 multidimensional arrays in terms of C's existing type-2 multidimensional arrays, it helps to clarify that the interface is low-level, \ie a C/\CFA array interface includes the resulting memory layout. 850 Specifically, the defining requirement of a type-2 system is the ability to slice a column from a column-finest matrix. 851 Hence, the required memory shape of such a slice is fixed, before any discussion of implementation. 852 The implementation presented here is how the \CFA array-library wrangles the C type system to make it do memory steps that are consistent with this layout while not affecting legacy C programs. 849 853 % TODO: do I have/need a presentation of just this layout, just the semantics of -[all]? 850 854 … … 874 878 \lstinput[aboveskip=0pt]{145-145}{hello-md.cfa} 875 879 The nontrivial slicing in this example now allows passing a \emph{noncontiguous} slice to @print1d@, where the new-array library provides a ``subscript by all'' operation for this purpose. 876 In a multi-dimensional subscript operation, any dimension given as @all@ is a placeholder, \ie ``not yet subscripted by a value'', waiting for such a value,implementing the @ar@ trait.880 In a multi-dimensional subscript operation, any dimension given as @all@ is a placeholder, \ie ``not yet subscripted by a value'', waiting for a value implementing the @ar@ trait. 877 881 \lstinput{150-151}{hello-md.cfa} 878 882 … … 948 952 A column is almost ready to be arranged into a matrix; 949 953 it is the \emph{contained value} of the next-level building block, but another lie about size is required. 950 At first, an atom needs to be arranged as if it werebigger, but now a column needs to be arranged as if it is smaller (the left diagonal above it, shrinking upward).954 At first, an atom needs to be arranged as if it is bigger, but now a column needs to be arranged as if it is smaller (the left diagonal above it, shrinking upward). 951 955 These lying columns, arranged contiguously according to their size (as announced) form the matrix @x[all]@. 952 956 Because @x[all]@ takes indices, first for the fine stride, then for the coarse stride, it achieves the requirement of representing the transpose of @x@. … … 1020 1024 1021 1025 1022 \section{Bound Checks, Added and Removed} 1023 1026 \section{Zero Overhead} 1027 1028 At runtime, the \CFA array is exactly a C array. 1024 1029 \CFA array subscripting is protected with runtime bound checks. 1025 The array dependent-typing provides information to the C optimizer allowing it remove many of the bound checks. 1026 This section provides a demonstration of the effect. 1027 1028 The experiment compares the \CFA array system with the padded-room system [TODO:xref] most typically exemplified by Java arrays, but also reflected in the \CC pattern where restricted vector usage models a checked array. 1029 The essential feature of this padded-room system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based. 1030 The experiment compares with the \CC version to keep access to generated assembly code simple. 1030 The array dependent-typing provides information to the C optimizer, allowing it remove many of the bound checks. 1031 This section provides a demonstration of these effects. 1032 1033 The experiment compares the \CFA array system with the simple-safety system most typically exemplified by Java arrays (\VRef[Section]{JavaCompare}), but also reflected in the \CC pattern where restricted vector usage models a checked array (\VRef[Section]{CppCompare}). 1034 The essential feature of this simple system is the one-to-one correspondence between array instances and the symbolic bounds on which dynamic checks are based. 1035 The experiment uses the \CC version to simplify access to generated assembly code. 1036 While ``\CC'' labels a participant, it is really the simple-safety system (of @vector@ with @.at@) whose limitations are being explained, and not limitations of \CC optimization. 1031 1037 1032 1038 As a control case, a simple loop (with no reused dimension sizes) is seen to get the same optimization treatment in both the \CFA and \CC versions. 1033 When the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code. 1034 But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assembly, ready to catch an occurrence the mistake. 1035 1036 TODO: paste source and assembly codes 1037 1038 Incorporating reuse among dimension sizes is seen to give \CFA an advantage at being optimized. 1039 The case is naive matrix multiplication over a row-major encoding. 1040 1041 TODO: paste source codes 1039 Firstly, when the programmer treats the array's bound correctly (making the subscript ``obviously fine''), no dynamic bound check is observed in the program's optimized assembly code. 1040 But when the bounds are adjusted, such that the subscript is possibly invalid, the bound check appears in the optimized assembly, ready to catch a mistake. 1041 1042 \VRef[Figure]{f:ovhd-ctl} gives a control-case example of summing values in an array, where each column shows the program in languages C (a,~d,~g), \CFA (b,~e,~h), and \CC (c,~f,~i). 1043 The C code has no bounds checking, while the \CFA and \CC can have bounds checking. 1044 The source-code functions in (a, b, c) can be compiled to have either correct or incorrect uses of bounds. 1045 When compiling for correct bound use, the @BND@ macro passes its argument through, so the loops cover exactly the passed array sizes. 1046 When compiling for possible incorrect bound use (a programming error), the @BND@ macro hardcodes the loops for 100 iterations, which implies out-of-bound access attempts when the passed array has fewer than 100 elements. 1047 The assembly code excerpts show optimized translations for correct-bound mode in (d, e, f) and incorrect-bound mode in (g, h, i). 1048 Because incorrect-bound mode hardcodes 100 iterations, the loop always executes a first time, so this mode does not have the @n == 0@ branch seen in correct-bound mode. 1049 For C, this difference is the only (d--g) difference. 1050 For correct bounds, the \CFA translation equals the C translation, \ie~there is no (d--e) difference, while \CC has an additional indirection to dereference the vector's auxiliary allocation. 1051 1052 \begin{figure} 1053 \setlength{\tabcolsep}{10pt} 1054 \begin{tabular}{llll@{}} 1055 \multicolumn{1}{c}{C} & 1056 \multicolumn{1}{c}{\CFA} & 1057 \multicolumn{1}{c}{\CC (nested vector)} 1058 \\[1em] 1059 \lstinput{20-28}{ar-bchk/control.c} & 1060 \lstinput{20-28}{ar-bchk/control.cfa} & 1061 \lstinput{20-28}{ar-bchk/control.cc} 1062 \\ 1063 \multicolumn{1}{c}{(a)} & 1064 \multicolumn{1}{c}{(b)} & 1065 \multicolumn{1}{c}{(c)} 1066 \\[1em] 1067 \multicolumn{4}{l}{ 1068 \includegraphics[page=1,trim=0 9.125in 2in 0,clip]{ar-bchk} 1069 } 1070 \\ 1071 \multicolumn{1}{c}{(d)} & 1072 \multicolumn{1}{c}{(e)} & 1073 \multicolumn{1}{c}{(f)} 1074 \\[1em] 1075 \multicolumn{4}{l}{ 1076 \includegraphics[page=2,trim=0 8.75in 2in 0,clip]{ar-bchk} 1077 } 1078 \\ 1079 \multicolumn{1}{c}{(g)} & 1080 \multicolumn{1}{c}{(h)} & 1081 \multicolumn{1}{c}{(i)} 1082 \end{tabular} 1083 \caption{Overhead comparison, control case. 1084 All three programs/compilers generate equally performant code when the programmer ``self-checks'' bounds via a loop's condition. 1085 Yet both \CFA and \CC versions generate code that is slower and safer than C's when the programmer might overrun the bounds.} 1086 \label{f:ovhd-ctl} 1087 \end{figure} 1088 1089 Differences arise when the bound-incorrect programs are passed an array shorter than 100. 1090 The C version, (g), proceeds with undefined behaviour, reading past the end of the array. 1091 The \CFA and \CC versions, (h, i), flag the mistake with the runtime check, the @i >= n@ branch. 1092 This check is provided implicitly by the library types @array@ and @vector@, respectively. 1093 The significant result is the \emph{absence} of runtime checks from the bound-correct translations, (e, f). 1094 The code optimizer has removed them because, at the point where they would occur (immediately past @.L28@/@.L3@), it knows from the surrounding control flow either @i == 0 && 0 < n@ or @i < n@ (directly), \ie @i < n@ either way. 1095 So any repeated checks, \ie the branch and its consequent code (raise error), are removable. 1096 1097 % Progressing from the control case, a deliberately bound-incorrect mode is no longer informative. 1098 % Rather, given a (well-typed) program that does good work on good data, the issue is whether it is (determinably) bound-correct on all data. 1099 1100 When dimension sizes get reused, \CFA has an advantage over \CC-vector at getting simply written programs well optimized. 1101 The example case of \VRef[Figures]{f:ovhd-treat-src} and \VRef[]{f:ovhd-treat-asm} is a simple matrix multiplication over a row-major encoding. 1102 Simple means coding directly to the intuition of the mathematical definition without trying to optimize for memory layout. 1103 In the assembly code of \VRef[Figure]{f:ovhd-treat-asm}, the looping pattern of \VRef[Figure]{f:ovhd-ctl} (d, e, f), ``Skip ahead on zero; loop back for next,'' occurs with three nesting levels. 1104 Simultaneously, the dynamic bound-check pattern of \VRef[Figure]{f:ovhd-ctl} (h,~i), ``Get out on invalid,'' occurs, targeting @.L7@, @.L9@ and @.L8@ (bottom right). 1105 Here, \VRef[Figures]{f:ovhd-treat-asm} shows the \CFA solution optimizing into practically the C solution, while the \CC solution shows added runtime bound checks. 1106 Like in \VRef[Figure]{f:ovhd-ctl} (e), the significance is the \emph{absence} of library-imposed runtime checks, even though the source code is working through the the \CFA @array@ library. 1107 The optimizer removed the library-imposed checks because the data structure @array@-of-@array@ is constrained by its type to be shaped correctly for the intuitive looping. 1108 In \CC, the same constraint does not apply to @vector@-of-@vector@. 1109 Because every individual @vector@ carries its own size, two types of bound mistakes are possible. 1110 1111 \begin{figure} 1112 \setlength{\tabcolsep}{10pt} 1113 \begin{tabular}{llll@{}} 1114 \multicolumn{1}{c}{C} & 1115 \multicolumn{1}{c}{\CFA} & 1116 \multicolumn{1}{c}{\CC (nested vector)} 1117 \\ 1118 \lstinput{20-37}{ar-bchk/treatment.c} & 1119 \lstinput{20-37}{ar-bchk/treatment.cfa} & 1120 \lstinput{20-37}{ar-bchk/treatment.cc} 1121 \end{tabular} 1122 \caption{Overhead comparison, differentiation case, source.} 1123 \label{f:ovhd-treat-src} 1124 \end{figure} 1125 1126 \begin{figure} 1127 \newcolumntype{C}[1]{>{\centering\arraybackslash}p{#1}} 1128 \begin{tabular}{C{1.5in}C{1.5in}C{1.5in}p{1in}} 1129 C & 1130 \CFA & 1131 \CC (nested vector) 1132 \\[1em] 1133 \multicolumn{4}{l}{ 1134 \includegraphics[page=3,trim=0 4in 2in 0,clip]{ar-bchk} 1135 } 1136 \end{tabular} 1137 \caption{Overhead comparison, differentiation case, assembly. 1138 } 1139 \label{f:ovhd-treat-asm} 1140 \end{figure} 1141 1142 In detail, the three structures received may not be matrices at all, per the obvious/dense/total interpretation; rather, any one might be ragged-right in its rows. 1143 The \CFA solution guards against this possibility by encoding the minor length (number of columns) in the major element (row) type. 1144 In @res@, for example, each of the @M@ rows is @array(float, N)@, guaranteeing @N@ cells within it. 1145 Or more technically, guaranteeing @N@ as the basis for the imposed bound check \emph{of every row.} 1146 As well, the \CC type does not impose the mathematically familiar constraint of $(M \times P) (P \times N) \rightarrow (M \times N)$. 1147 Even assuming away the first issue, \eg that in @lhs@, all minor/cell counts agree, the data format allows the @rhs@ major/row count to disagree. 1148 Or, the possibility that the row count @res.size()@ disagrees with the row count @lhs.size()@ illustrates this bound-mistake type in isolation. 1149 The \CFA solution guards against this possibility by keeping length information separate from the array data, and therefore eligible for sharing. 1150 This capability lets \CFA escape the one-to-one correspondence between array instances and symbolic bounds, where this correspondence leaves a \CC-vector programmer stuck with a matrix representation that repeats itself. 1151 1152 It is important to clarify that the \CFA solution does not become unsafe (like C) in losing its dynamic checks, even though it becomes fast (as C) in losing them. 1153 The dynamic checks are dismissed as unnecessary \emph{because} the program is safe to begin with. 1154 To achieve the same performance, a \CC programmer must state appropriate assertions or assumptions, to allow the optimizer to dismiss the runtime checks. 1155 % Especially considering that two of them are in the inner-most loop. 1156 The solution requires doing the work of the inner-loop checks as a \emph{preflight step}. 1157 But this step requires looping and doing it upfront gives too much separation for the optimizer to see ``has been checked already'' in the deep loop. 1158 So, the programmer must restate the preflight observation within the deep loop, but this time as an unchecked assumption. 1159 Such assumptions are risky because they introduce further undefined behaviour when misused. 1160 Only the programmer's discipline remains to ensure this work is done without error. 1161 1162 In summary, the \CFA solution lets a simply stated program have dynamic guards that catch bugs, while letting a simply stated bug-free program run as fast as the unguarded C equivalent. 1163 1164 \begin{comment} 1165 The ragged-right issue brings with it a source-of-truth difficulty: Where, in the \CC version, is one to find the value of $N$? $M$ can come from either @res@'s or @lhs@'s major/row count, and checking these for equality is straightforward. $P$ can come from @rhs@'s major/row count. But $N$ is only available from columns, \ie minor/cell counts, which are ragged. So any choice of initial source of truth, \eg 1166 \end{comment} 1042 1167 1043 1168 … … 1209 1334 However, it only needs @float@'s default constructor, as the other operations are never used. 1210 1335 Current work by the \CFA team aims to improve this situation. 1211 Therefore, I had to construct a workaround.1212 1213 1336 My workaround moves from otype (value) to dtype (pointer) with a default-constructor assertion, where dtype does not generate any constructors but the assertion claws back the default otype constructor. 1214 1337 \begin{cquote} … … 1408 1531 1409 1532 \subsection{Java} 1533 \label{JavaCompare} 1410 1534 1411 1535 Java arrays are references, so multi-dimension arrays are arrays-of-arrays \see{\VRef{toc:mdimpl}}. … … 1496 1620 1497 1621 \subsection{\CC} 1622 \label{CppCompare} 1498 1623 1499 1624 Because C arrays are difficult and dangerous, the mantra for \CC programmers is to use @std::vector@ in place of the C array. 1500 While the vector size can grow and shrink dynamically, \vs a fixed-size dynamic size with VLAs, the cost of this extra feature is mitigated by preallocating the maximum size (like the VLA) at the declaration (one dynamic call) to avoid using @push_back@. 1625 While the vector size can grow and shrink dynamically, \vs an unchanging dynamic size with VLAs, the cost of this extra feature is mitigated by preallocating the maximum size (like the VLA) at the declaration. 1626 So, it costs one upfront dynamic allocation and avoids growing the array through pushing. 1501 1627 \begin{c++} 1502 1628 vector< vector< int > > m( 5, vector<int>(8) ); // initialize size of 5 x 8 with 6 dynamic allocations 1503 1629 \end{c++} 1504 1630 Multidimensional arrays are arrays-of-arrays with associated costs. 1505 Each @vector@ array has an array descriptor contain the dimension, which allows bound checked using @x.at(i)@ in place of @x[i]@. 1506 Used with these restrictions, out-of-bound accesses are caught, and in-bound accesses never exercise the vector's ability to grow, preventing costly reallocate and copy, and never invalidate references to contained values. 1507 This scheme matches Java's safety and expressiveness exactly, but with the inherent costs. 1508 1509 1631 Each @vector@ array has an array descriptor containing the dimension, which allows bound checked using @x.at(i)@ in place of @x[i]@. 1632 Used with these restrictions, out-of-bound accesses are caught, and in-bound accesses never exercise the vector's ability to grow, preventing costly reallocate-and-copy, and never invalidating references to contained values. 1633 1634 This scheme matches a Java array's safety and expressiveness exactly, with the same inherent costs. 1635 Notably, a \CC vector of vectors does not provide contiguous element storage (even when upfront allocation is done carefully) because a vector puts its elements in an auxiliary allocation. 1636 So, in spite of @vector< vector< int > >@ appearing to be ``everything by value,'' it is still a first array whose elements include pointers to further arrays. 1637 1638 \CC has options for working with memory-adjacent data in desirable ways, particularly in recent revisions. 1639 But none makes an allocation with a dynamically given fixed size less awkward than the vector arrangement just described. 1640 1641 \CC~26 adds @std::inplace_vector@, which provides an interesting vector--array hybrid,\footnote{ 1642 Like a vector, it lets a user construct elements in a loop, rather than imposing uniform construction. 1643 Yet it preserves \lstinline{std::array}'s ability to be entirely stack-allocated, by avoiding an auxiliary elements' allocation. 1644 } but does not change the fundamental limit of \lstinline{std::array}, that the length, being a template parameter, must be a static value. 1645 1646 \CC~20's @std::span@ is a view that unifies true arrays, vectors, static sizes and dynamic sizes, under a common API that adds bounds checking. 1647 When wrapping a vector, bounds checking occurs on regular subscripting, \ie one need not remember to use @.at@. 1648 When wrapping a locally declared fixed-size array, bound communication is implicit. 1649 But it has a soundness gap by offering construction from pointer and user-given length. 1650 1651 \CC~23's @std::mdspan@ adds multidimensional indexing and reshaping capabilities analogous to those built into \CFA's @array@. 1652 Like @span@, it works over multiple underlying container types. 1653 But neither @span@ nor @mdspan@ augments the available allocation options. 1654 1655 Thus, these options do not offer an allocation with a dynamically given fixed size. 1656 And furthermore, they do not provide any improvement to the C flexible array member pattern, for making a dynamic amount of storage contiguous with its header, as do \CFA's accordions. 1657 1658 1659 \begin{comment} 1510 1660 \subsection{Levels of Dependently Typed Arrays} 1511 1661 1662 TODO: fix the position; checked c does not do linear types 1512 1663 \CFA's array is the first lightweight application of dependently-typed bound tracking to an extension of C. 1513 1664 Other extensions of C that apply dependently-typed bound tracking are heavyweight, in that the bound tracking is part of a linearly-typed ownership-system, which further helps guarantee statically the validity of every pointer deference. … … 1543 1694 it can also do these other cool checks, but watch how I can mess with its conservativeness and termination 1544 1695 1545 Two c urrent, state-of-the-art array languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, offer novel contributions concerningsimilar, restricted dependent types for tracking array length.1696 Two contemporary array-centric languages, Dex\cite{arr:dex:long} and Futhark\cite{arr:futhark:tytheory}, contribute similar, restricted dependent types for tracking array length. 1546 1697 Unlike \CFA, both are garbage-collected functional languages. 1547 1698 Because they are garbage-collected, referential integrity is built-in, meaning that the heavyweight analysis, that \CFA aims to avoid, is unnecessary. … … 1554 1705 There is a particular emphasis on an existential type, enabling callee-determined return shapes. 1555 1706 1556 1557 Dex uses a novel conception of size, embedding its quantitative information completely into an ordinary type. 1558 1559 Futhark and full-strength dependently typed languages treat array sizes are ordinary values. 1707 Dex uses an Ada-style conception of size, embedding quantitative information completely into an ordinary type. 1708 1709 Futhark and full-strength dependently typed languages treat array sizes as ordinary values. 1560 1710 Futhark restricts these expressions syntactically to variables and constants, while a full-strength dependent system does not. 1561 1711 1562 \CFA's hybrid presentation, @forall( [N] )@, has @N@ belonging to the type system, yet has no instances.1712 \CFA's hybrid presentation, @forall( [N] )@, has @N@ belonging to the type system, yet no objects of type @[N]@ occur. 1563 1713 Belonging to the type system means it is inferred at a call site and communicated implicitly, like in Dex and unlike in Futhark. 1564 1714 Having no instances means there is no type for a variable @i@ that constrains @i@ to be in the range for @N@, unlike Dex, [TODO: verify], but like Futhark. … … 1569 1719 1570 1720 In Ada and Dex, an array is conceived as a function whose domain must satisfy only certain structural assumptions, while in C, \CC, Java, Futhark and \CFA today, the domain is a prefix of the natural numbers. 1571 The generality has obvious aesthetic benefits for programmers working on scheduling resources to weekdays, and for programmers who prefer to count from an initial number of their own choosing. 1721 The Ada--Dex generality has aesthetic benefits for certain programmers. For those working on scheduling resources to weekdays: 1722 For those who prefer to count from an initial number of their own choosing: 1572 1723 1573 1724 This change of perspective also lets us remove ubiquitous dynamic bound checks. … … 1605 1756 (unsafe_from_ordinal a (idiv o bs), unsafe_from_ordinal b (rem o bs)) 1606 1757 \end{cfa} 1758 % fix mike's syntax highlighter 1607 1759 and by a user-provided adapter expression at the call site that shows how to indexing with a tuple is backed by indexing each dimension at a time 1608 1760 \begin{cfa} … … 1616 1768 1617 1769 \subsection{Static Safety in C Extensions} 1770 \end{comment} 1618 1771 1619 1772 1620 1773 \section{Future Work} 1621 1774 1622 \subsection{Array Syntax}1623 1624 An important goal is to recast @array(...)@ syntax into C-style @[]@.1625 The proposal (which is partially implemented) is an alternate dimension and subscript syntax .1626 C multi-dimension and subscripting syntax uses multiple bracket s.1627 \begin{cfa} 1628 int m@[2][3]@; // dimension1629 m@[0][1]@ = 3; // subscript1630 \end{cfa} 1631 Leveraging this syntax, the following (simpler) syntax should be intuitive to C programmers with only a small backwards compatibility issue. 1632 \begin{cfa} 1633 int m@[2, 3]@; // dimension1634 m@[0, 1]@ = 3; // subscript1635 \end{cfa} 1636 However, the new subscript syntax is not backwards compatible, as @0, 1@ is a comma expression.1637 Interestingly, disallowed the comma expression in this context eliminates an unreported error: subscripting a matrix with @m[i, j]@ instead of @m[i][j]@, which selects the @j@th row not the @i, j@ element.1638 Hence, a comma expression in this context is rare. 1639 Finally, it is possible to write @m[(i, j)]@ in the new syntax to achieve the equivalent of the old @m[i, j]@. 1640 Note, the new subscript syntax can easily be internally lowered to @[-][-]...@ and handled as regular subscripting. 1641 The only ambiguity with C syntax is for a single dimension array, where the syntax for old and new are the same. 1642 \begin{cfa} 1643 int m[2@,@]; // single dimension 1644 m[0] = 3; // subscript 1645 \end{cfa} 1646 The solution for the dimension is to use a terminating comma to denote a new single-dimension array. 1647 This syntactic form is also used for the (rare) singleton tuple @[y@{\ color{red},}@]@.1775 % \subsection{Array Syntax} 1776 1777 An important goal is to recast \CFA-style @array(...)@ syntax into C-style array syntax. 1778 The proposal (which is partially implemented) is an alternate dimension and subscript syntax for multi-dimension arrays. 1779 C multi-dimension and subscripting syntax uses multiple bracketed constants/expressions. 1780 \begin{cfa} 1781 int m@[2][3]@; // dimension 1782 m@[0][1]@ = 3; // subscript 1783 \end{cfa} 1784 The alternative \CFA syntax is a comma separated list: 1785 \begin{cfa} 1786 int m@[2, 3]@; // dimension 1787 m@[0, 1]@ = 3; // subscript 1788 \end{cfa} 1789 which should be intuitive to C programmers and is used in mathematics $M_{i,j}$ and other programing languages, \eg PL/I, Fortran. 1790 With respect to the dimension expressions, C only allows an assignment expression, not a comma expression. 1791 \begin{cfa} 1792 a[i, j]; 1793 test.c:3:16: error: expected ']' before ',' token 1794 \end{cfa} 1795 However, there is an ambiguity for a single dimension array, where the syntax for old and new arrays are the same, @int ar[10]@. 1796 The solution is to use a terminating comma to denote a \CFA-style single-dimension array. 1797 \begin{cfa} 1798 int ar[2$\Huge\color{red},$]; // single dimension new array 1799 \end{cfa} 1800 This syntactic form is also used for the (rare) singleton tuple @[y@{\Large\color{red},}@]@. 1648 1801 The extra comma in the dimension is only mildly annoying, and acts as eye-candy differentiating old and new arrays. 1649 The subscript operator is not an issue as overloading selects the correct single-dimension operation for old/new array types. 1650 The ultimately goal is to replace all C arrays with \CFA arrays, establishing a higher level of safety in C programs, and eliminating the need for the terminating comma. 1651 1652 1802 Hence, \CFA can repurpose the comma expression in this context for a list of dimensions. 1803 The ultimate goal is to replace all C arrays with \CFA arrays, establishing a higher level of safety in C programs, and eliminating the need for the terminating comma. 1804 With respect to the subscript expression, the comma expression is allowed. 1805 However, a comma expression in this context is rare, and is most commonly a (silent) mistake: subscripting a matrix with @m[i, j]@ instead of @m[i][j]@ selects the @j@th row not the @i, j@ element. 1806 It is still possible to write @m[(i, j)]@ in the new syntax to achieve the equivalent of the old @m[i, j]@. 1807 Internally, the compiler must de-sugar @[i, j, k]@ into @[i][j][k]@ to match with three calls to subscript operators. 1808 Note, there is no ambiguity for subscripting a single dimensional array, as the subscript operator selects the correct form from the array type. 1809 Currently, @array@ supports the old and new subscript syntax \see{\VRef[Figure]{f:ovhd-treat-src}}, including combinations of new and old, @arr[1, 2][3]@. 1810 The new subscript syntax can be extended to C arrays for uniformity, but requires the non-compatible removal of the (rare) comma-expression as a subscript. 1811 1812 1813 \begin{comment} 1653 1814 \subsection{Range Slicing} 1654 1815 … … 1659 1820 1660 1821 1661 \begin{comment}1662 1822 \section{\texorpdfstring{\CFA}{Cforall}} 1663 1823 … … 1697 1857 Using a compiler-produced value eliminates an opportunity for user error. 1698 1858 1699 TODO:fix in following: even the alloc call gives bad code gen: verify it was always this way; walk back the wording about things just working here; assignment (rebind) seems to offer workaround, as in bkgd-cfa-arrayinteract.cfa1859 ...someday... fix in following: even the alloc call gives bad code gen: verify it was always this way; walk back the wording about things just working here; assignment (rebind) seems to offer workaround, as in bkgd-cfa-arrayinteract.cfa 1700 1860 1701 1861 Bringing in another \CFA feature, reference types, both resolves a sore spot of the last example, and gives a first example of an array-interaction bug. … … 1706 1866 (*ar2)[5]; 1707 1867 \end{cfa} 1708 Using ``reference to array'' works at resolving this issue. TODO:discuss connection with Doug-Lea \CC proposal.1868 Using ``reference to array'' works at resolving this issue. ...someday... discuss connection with Doug-Lea \CC proposal. 1709 1869 \begin{cfa} 1710 1870 tm (&ar3)[10] = *alloc(); … … 1714 1874 1715 1875 Using proper array types (@ar2@ and @ar3@) addresses a concern about using raw element pointers (@ar1@), albeit a theoretical one. 1716 TODOxref C standard does not claim that @ar1@ may be subscripted,1876 ...someday... xref C standard does not claim that @ar1@ may be subscripted, 1717 1877 because no stage of interpreting the construction of @ar1@ has it be that ``there is an \emph{array object} here.'' 1718 1878 But both @*ar2@ and the referent of @ar3@ are the results of \emph{typed} @alloc@ calls, … … 1720 1880 1721 1881 The ``reference to array'' type has its sore spots too. 1722 TODOsee also @dimexpr-match-c/REFPARAM_CALL@ (under @TRY_BUG_1@)1723 1724 TODO:I fixed a bug associated with using an array as a T. I think. Did I really? What was the bug?1882 ...someday... see also @dimexpr-match-c/REFPARAM_CALL@ (under @TRY_BUG_1@) 1883 1884 ...someday... I fixed a bug associated with using an array as a T. I think. Did I really? What was the bug? 1725 1885 \end{comment}
Note:
See TracChangeset
for help on using the changeset viewer.