Changeset bedb40e
- Timestamp:
- Sep 10, 2018, 5:17:34 PM (5 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
- Children:
- 67982887, 9fce933a
- Parents:
- 0cf9ffd (diff), e15ba975 (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. - Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/bibliography/pl.bib
r0cf9ffd rbedb40e 939 939 title = {\textsf{C}$\mathbf{\forall}$ : Adding Modern Programming Language Features to C}, 940 940 year = 2018, 941 month = aug, 941 942 journal = spe, 942 note = { Accepted, to appear},943 note = {http://dx.doi.org/10.1002/spe.2624}, 943 944 } 944 945 … … 962 963 comment = { 963 964 The evidence given is thin. 964 } 965 }, 965 966 } 966 967 … … 1827 1828 key = {Peter Buhr}, 1828 1829 title = {CS343}, 1829 year = 201 7,1830 year = 2018, 1830 1831 howpublished= {\href{https://www.student.cs.uwaterloo.ca/~cs343}{https://\-www.student.cs.uwaterloo.ca/\-~cs343}}, 1831 1832 } … … 3362 3363 author = {Peter Buhr and David Dice and Wim H. Hesselink}, 3363 3364 journal = ccpe, 3364 volume opt= 30,3365 number opt = 4,3365 volume = 30, 3366 number = 18, 3366 3367 year = 2018, 3367 month = may,3368 month = sep, 3368 3369 publisher = {John Wiley \& Sons}, 3369 3370 note = {\url{https://doi-org.proxy.lib.uwaterloo.ca/10.1002/cpe.4475}} … … 3849 3850 keywords = {concurrency, critical section}, 3850 3851 contributer = {pabuhr@plg}, 3851 author = {Dominic Duggan and G .V. Cormack and John Ophel},3852 author = {Dominic Duggan and Gordon V. Cormack and John Ophel}, 3852 3853 title = {Kinded Type Inference for Parametric Overloading}, 3853 3854 journal = acta, … … 5855 5856 keywords = {Cyclone, existential types, polymorphism, type variables}, 5856 5857 contributer = {a3moss@plg}, 5857 author = {D .Grossman},5858 author = {Dan Grossman}, 5858 5859 title = {Quantified Types in an Imperative Language}, 5859 5860 journal = toplas, -
doc/user/user.tex
r0cf9ffd rbedb40e 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Thu Jul 26 17:29:05201814 %% Update Count : 33 6613 %% Last Modified On : Fri Aug 31 07:54:50 2018 14 %% Update Count : 3396 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 210 210 Even with all its problems, C continues to be popular because it allows writing software at virtually any level in a computer system without restriction. 211 211 For system programming, where direct access to hardware, storage management, and real-time issues are a requirement, C is usually the only language of choice. 212 The TIOBE index~\cite{TIOBE} for July 2018 ranks the top 5 most \emph{popular} programming languages as:\Index*{Java} 16\%, C 14\%, \Index*[C++]{\CC{}} 7.5\%, Python 6\%, Visual Basic 4\% = 47.5\%, where the next 50 languages are less than 4\% each, with a long tail.212 The TIOBE index~\cite{TIOBE} for July 2018 ranks the top five most \emph{popular} programming languages as \Index*{Java} 16\%, C 14\%, \Index*[C++]{\CC{}} 7.5\%, Python 6\%, Visual Basic 4\% = 47.5\%, where the next 50 languages are less than 4\% each, with a long tail. 213 213 The top 3 rankings over the past 30 years are: 214 214 \begin{center} … … 351 351 The 2011 C standard plus GNU extensions. 352 352 \item 353 \Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline] @-fgnu89-inline@}}353 \Indexc[deletekeywords=inline]{-fgnu89-inline}\index{compilation option!-fgnu89-inline@{\lstinline[deletekeywords=inline]$-fgnu89-inline$}} 354 354 Use the traditional GNU semantics for inline routines in C11 mode, which allows inline routines in header files. 355 355 \end{description} … … 455 455 #endif 456 456 457 ®#include_next <bfdlink.h> 457 ®#include_next <bfdlink.h> §\C{// must have internal check for multiple expansion}§ 458 458 ® 459 459 #if defined( with ) && defined( __CFA_BFD_H__ ) §\C{// reset only if set}§ … … 504 504 505 505 C, \CC, and Java (and many other programming languages) have no exponentiation operator\index{exponentiation!operator}\index{operator!exponentiation}, \ie $x^y$, and instead use a routine, like \Indexc{pow}, to perform the exponentiation operation. 506 \CFA extends the basic operators with the exponentiation operator ©?\?©\index{?\\?@ \lstinline@?\?@} and ©?\=?©\index{?\\=?@\lstinline@?\=?@}, as in, ©x \ y© and ©x \= y©, which means $x^y$ and $x \leftarrow x^y$.506 \CFA extends the basic operators with the exponentiation operator ©?\?©\index{?\\?@©?\?©} and ©?\=?©\index{?\\=?@©\=?©}, as in, ©x \ y© and ©x \= y©, which means $x^y$ and $x \leftarrow x^y$. 507 507 The priority of the exponentiation operator is between the cast and multiplicative operators, so that ©w * (int)x \ (int)y * z© is parenthesized as ©((w * (((int)x) \ ((int)y))) * z)©. 508 508 … … 516 516 256 64 -64 0.015625 -0.015625 18.3791736799526 0.264715-1.1922i 517 517 \end{cfa} 518 Parenthesis are necessary for the complex constants or the expression is parsed as ©1.0f+(2.0fi \ 3.0f)+2.0fi©.518 Parenthesis are necessary for complex constants or the expression is parsed as ©1.0f+®(®2.0fi \ 3.0f®)®+2.0fi©. 519 519 The exponentiation operator is available for all the basic types, but for user-defined types, only the integral-computation versions are available. 520 520 For returning an integral value, the user type ©T© must define multiplication, ©*©, and one, ©1©; … … 527 527 528 528 529 %\subsection{\texorpdfstring{\protect\lstinline@if@ Statement}{if Statement}} 530 \subsection{\texorpdfstring{\LstKeywordStyle{if} Statement}{if Statement}} 531 532 The ©if© expression allows declarations, similar to ©for© declaration expression: 533 \begin{cfa} 534 if ( int x = f() ) ... §\C{// x != 0}§ 535 if ( int x = f(), y = g() ) ... §\C{// x != 0 \&\& y != 0}§ 536 if ( int x = f(), y = g(); ®x < y® ) ... §\C{// relational expression}§ 537 \end{cfa} 538 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if© expression, and the results are combined using the logical ©&&© operator.\footnote{\CC only provides a single declaration always compared not equal to 0.} 529 %\subsection{\texorpdfstring{\protect\lstinline@if@/\protect\lstinline@while@ Statement}{if Statement}} 530 \subsection{\texorpdfstring{\LstKeywordStyle{if}/\LstKeywordStyle{while} Statement}{if/while Statement}} 531 532 The ©if©/©while© expression allows declarations, similar to ©for© declaration expression. 533 (Does not make sense for ©do©-©while©.) 534 \begin{cfa} 535 if ( ®int x = f()® ) ... §\C{// x != 0}§ 536 if ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§ 537 if ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§ 538 if ( ®struct S { int i; } x = { f() }; x.i < 4® ) §\C{// relational expression}§ 539 540 while ( ®int x = f()® ) ... §\C{// x != 0}§ 541 while ( ®int x = f(), y = g()® ) ... §\C{// x != 0 \&\& y != 0}§ 542 while ( ®int x = f(), y = g(); x < y® ) ... §\C{// relational expression}§ 543 while ( ®struct S { int i; } x = { f() }; x.i < 4® ) ... §\C{// relational expression}§ 544 \end{cfa} 545 Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the ©if©/©while© expression, and the results are combined using the logical ©&&© operator.\footnote{\CC only provides a single declaration always compared not equal to 0.} 539 546 The scope of the declaration(s) is local to the @if@ statement but exist within both the ``then'' and ``else'' clauses. 547 548 549 %\subsection{\texorpdfstring{\protect\lstinline@for@ Statement}{for Statement}} 550 \subsection{\texorpdfstring{\LstKeywordStyle{for} Statement}{for Statement}} 551 552 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges. 553 An empty conditional implies ©1©. 554 The up-to range ©~©\index{~@©~©} means exclusive range [M,N); 555 the up-to range ©~=©\index{~=@©~=©} means inclusive range [M,N]. 556 The down-to range ©-~©\index{-~@©-~©} means exclusive range [N,M); 557 the down-to range ©-~=©\index{-~=@©-~=©} means inclusive range [N,M]. 558 ©0© is the implicit start value; 559 ©1© is the implicit increment value for an up-to range and ©-1© for an implicit down-to range. 560 The loop index is polymorphic in the type of the start value or comparison value when start is implicitly ©0©. 561 \begin{cquote} 562 \begin{tabular}{@{}ll|l@{}} 563 \multicolumn{2}{c|}{for control} & \multicolumn{1}{c}{output} \\ 564 \hline 565 \begin{cfa} 566 while ®()® { sout | "empty"; break; } 567 do { sout | "empty"; break; } while ®()®; 568 for ®()® { sout | "empty"; break; } 569 for ( ®0® ) { sout | "A"; } 570 for ( ®1® ) { sout | "A"; } 571 for ( ®10® ) { sout | "A"; } 572 for ( ®1 ~= 10 ~ 2® ) { sout | "B"; } 573 for ( ®10 -~= 1 ~ -2® ) { sout | "C"; } 574 for ( ®0.5 ~ 5.5® ) { sout | "D"; } 575 for ( ®5.5 -~ 0.5® ) { sout | "E"; } 576 for ( ®i; 10® ) { sout | i; } 577 for ( ®i; 1 ~= 10 ~ 2® ) { sout | i; } 578 for ( ®i; 10 -~= 1 ~ -2® ) { sout | i; } 579 for ( ®i; 0.5 ~ 5.5® ) { sout | i; } 580 for ( ®i; 5.5 -~ 0.5® ) { sout | i; } 581 for ( ®ui; 2u ~= 10u ~ 2u® ) { sout | ui; } 582 for ( ®ui; 10u -~= 2u ~ -2u® ) { sout | ui; } 583 int start = 3, comp = 10, inc = 2; 584 for ( ®i; start ~ comp ~ inc + 1® ) { sout | i; } 585 \end{cfa} 586 & 587 \begin{cfa} 588 sout | endl; 589 sout | endl; 590 sout | endl; 591 sout | endl; 592 sout | endl; 593 sout | endl; 594 sout | endl; 595 sout | endl; 596 sout | endl; 597 sout | endl; 598 sout | endl; 599 sout | endl; 600 sout | endl; 601 sout | endl; 602 sout | endl; 603 sout | endl; 604 sout | endl; 605 606 sout | endl; 607 \end{cfa} 608 & 609 \begin{cfa} 610 empty 611 empty 612 empty 613 614 A 615 A A A A A A A A A A 616 B B B B B 617 C C C C C 618 D D D D D 619 E E E E E 620 0 1 2 3 4 5 6 7 8 9 621 1 3 5 7 9 622 10 8 6 4 2 623 0.5 1.5 2.5 3.5 4.5 624 5.5 4.5 3.5 2.5 1.5 625 2 4 6 8 10 626 10 8 6 4 2 627 628 3 6 9 629 \end{cfa} 630 \end{tabular} 631 \end{cquote} 540 632 541 633 … … 800 892 801 893 894 % for () => for ( ;; ) 895 % for ( 10 - t ) => for ( typeof(10 - t) ? = 0 ; ? < 10 - t; ? += 1 ) // using 0 and 1 896 % for ( i ; 10 - t ) => for ( typeof(10 - t) i = 0 ; i < 10 - t; i += 1 ) // using 0 and 1 897 % for ( T i ; 10 - t ) => for ( T i = 0 ; i < 10 - t; i += 1 ) // using 0 and 1 898 % for ( 3~9 ) => for ( int ? = 3 ; ? < 9; ? += 1 ) // using 1 899 % for ( i ; 3~9 ) => for ( int i = 3 ; i < 9; i += 1 ) // using 1 900 % for ( T i ; 3~9 ) => for ( T i = 3 ; i < 9; i += 1 ) // using 1 901 902 802 903 %\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}} 803 904 \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}} … … 805 906 While C provides ©continue© and ©break© statements for altering control flow, both are restricted to one level of nesting for a particular control structure. 806 907 Unfortunately, this restriction forces programmers to use \Indexc{goto} to achieve the equivalent control-flow for more than one level of nesting. 807 To prevent having to switch to the ©goto©, \CFA extends the \Indexc{continue}\index{continue@ \lstinline@continue@!labelled}\index{labelled!continue@©continue©} and \Indexc{break}\index{break@\lstinline@break@!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85}, as in Java.908 To prevent having to switch to the ©goto©, \CFA extends the \Indexc{continue}\index{continue@©continue©!labelled}\index{labelled!continue@©continue©} and \Indexc{break}\index{break@©break©!labelled}\index{labelled!break@©break©} with a target label to support static multi-level exit\index{multi-level exit}\index{static multi-level exit}~\cite{Buhr85}, as in Java. 808 909 For both ©continue© and ©break©, the target label must be directly associated with a ©for©, ©while© or ©do© statement; 809 910 for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement. … … 890 991 \end{figure} 891 992 892 Both labelled ©continue© and ©break© are a ©goto©\index{goto@ \lstinline@goto@!restricted} restricted in the following ways:993 Both labelled ©continue© and ©break© are a ©goto©\index{goto@©goto©!restricted} restricted in the following ways: 893 994 \begin{itemize} 894 995 \item -
driver/as.cc
r0cf9ffd rbedb40e 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // as.c -- 7 // as.c -- map assembler file, scan for debug information. If found, expand file by one character and insert Cforall 8 // language code on the N line from the start of the debug information. 8 9 // 9 10 // Author : Peter A. Buhr 10 11 // Created On : Wed Aug 1 10:49:42 2018 11 12 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Aug 22 17:30:24201813 // Update Count : 9 313 // Last Modified On : Sat Sep 8 08:40:16 2018 14 // Update Count : 97 14 15 // 15 16 … … 43 44 off_t size = mystat.st_size; 44 45 45 char * start = (char *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); 46 if ( start == (void *)-1 ) { perror( "mmap" ); exit( EXIT_FAILURE ); }; 46 if ( size ) { // cannot map 0 sized file 47 char * start = (char *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); 48 if ( start == (void *)-1 ) { perror( "mmap" ); exit( EXIT_FAILURE ); }; 47 49 48 if ( char * cursor = strstr( start, ".Ldebug_info0:" ) ) { // debug information ?49 // Expand file by one byte to hold 2 character Cforall language code.50 if ( ftruncate( fd, size + 1 ) ) { perror( "ftruncate" ); exit( EXIT_FAILURE ); };50 if ( char * cursor = strstr( start, ".Ldebug_info0:" ) ) { // debug information ? 51 // Expand file by one byte to hold 2 character Cforall language code. 52 if ( ftruncate( fd, size + 1 ) ) { perror( "ftruncate" ); exit( EXIT_FAILURE ); }; 51 53 52 for ( int i = 0; i < 8; i += 1 ) {// move N (magic) lines forward53 cursor = strstr( cursor, "\n" ) + 1;54 } // for54 for ( int i = 0; i < 8; i += 1 ) { // move N (magic) lines forward 55 cursor = strstr( cursor, "\n" ) + 1; 56 } // for 55 57 56 cursor -= 2;// backup over "c\n" language value57 if ( *(cursor - 1) != 'x' ) { fprintf( stderr, "invalid C language code\n" ); exit( EXIT_FAILURE ); };58 cursor -= 2; // backup over "c\n" language value 59 if ( *(cursor - 1) != 'x' ) { fprintf( stderr, "invalid C language code\n" ); exit( EXIT_FAILURE ); }; 58 60 59 memmove( cursor + 2, cursor + 1, start + size - cursor - 1 ); // move remaining text 1 character right61 memmove( cursor + 2, cursor + 1, start + size - cursor - 1 ); // move remaining text 1 character right 60 62 61 *(cursor) = '2'; // replace C language value with CFA 62 *(cursor + 1) = '5'; 63 *(cursor) = '2'; // replace C language value with CFA 64 *(cursor + 1) = '5'; 65 } // if 66 67 if ( munmap( start, size ) ) { perror( "munmap" ); exit( EXIT_FAILURE ); }; // update on disk 63 68 } // if 64 65 if ( munmap( start, size ) ) { perror( "munmap" ); exit( EXIT_FAILURE ); }; // update on disk66 69 67 70 argv[0] = "as"; -
driver/cc1.cc
r0cf9ffd rbedb40e 10 10 // Created On : Fri Aug 26 14:23:51 2005 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 23 09:48:40201813 // Update Count : 12 212 // Last Modified On : Mon Sep 3 16:57:05 2018 13 // Update Count : 125 14 14 // 15 15 … … 32 32 string compiler_name( CFA_BACKEND_CC ); // path/name of C compiler 33 33 34 string D__GCC_X__( "-D__GCC_X__=" );35 34 string D__GCC_BPREFIX__( "-D__GCC_BPREFIX__=" ); 36 35 string D__CFA_FLAGPREFIX__( "-D__CFA_FLAG__=" ); … … 46 45 enum { NumSuffixes = 2 }; 47 46 const string suffixes[NumSuffixes] = { "cfa", "hfa", }; 48 49 47 50 48 void suffix( string arg, const char * args[], int & nargs ) { … … 116 114 void Stage1( const int argc, const char * const argv[] ) { 117 115 int code; 118 int i;119 116 120 117 string arg; … … 139 136 cerr << "Stage1" << endl; 140 137 #endif // __DEBUG_H__ 138 checkEnv( args, nargs ); // arguments passed via environment variables 139 #ifdef __DEBUG_H__ 140 for ( int i = 1; i < argc; i += 1 ) { 141 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; 142 } // for 143 #endif // __DEBUG_H__ 141 144 142 145 // process all the arguments 143 146 144 checkEnv( args, nargs ); // arguments passed via environment variables 145 146 for ( i = 1; i < argc; i += 1 ) { 147 #ifdef __DEBUG_H__ 148 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; 149 #endif // __DEBUG_H__ 147 for ( int i = 1; i < argc; i += 1 ) { 150 148 arg = argv[i]; 151 #ifdef __DEBUG_H__152 cerr << "arg:\"" << arg << "\"" << endl;153 #endif // __DEBUG_H__154 149 if ( prefix( arg, "-" ) ) { 155 150 // strip g++ flags that are inappropriate or cause duplicates in subsequent passes … … 185 180 ncargs += 1; 186 181 i += 1; // and the argument 187 // } else if ( prefix( arg, D__GCC_X__ ) ) {188 // args[nargs] = "-x";189 // nargs += 1;190 // args[nargs] = ( *new string( arg.substr( D__GCC_X__.size() ) ) ).c_str(); // pass the flag along191 // nargs += 1;192 // } else if ( arg == "-D" && prefix( argv[i + 1], D__GCC_X__.substr(2) ) ) {193 // args[nargs] = "-x";194 // nargs += 1;195 // args[nargs] = ( *new string( string( argv[i + 1] ).substr( D__GCC_X__.size() - 2 ) ) ).c_str(); // pass the flag along196 // nargs += 1;197 // i += 1; // and the argument198 182 } else if ( prefix( arg, D__GCC_BPREFIX__ ) ) { 199 183 bprefix = arg.substr( D__GCC_BPREFIX__.size() ); … … 251 235 #ifdef __DEBUG_H__ 252 236 cerr << "args:"; 253 for ( i = 1; i < nargs; i += 1 ) {237 for ( int i = 1; i < nargs; i += 1 ) { 254 238 cerr << " " << args[i]; 255 239 } // for … … 282 266 #ifdef __DEBUG_H__ 283 267 cerr << "nargs: " << nargs << endl; 284 for ( i = 0; args[i] != NULL; i += 1 ) {268 for ( int i = 0; args[i] != NULL; i += 1 ) { 285 269 cerr << args[i] << " "; 286 270 } // for … … 324 308 #ifdef __DEBUG_H__ 325 309 cerr << "cpp nargs: " << nargs << endl; 326 for ( i = 0; args[i] != NULL; i += 1 ) {310 for ( int i = 0; args[i] != NULL; i += 1 ) { 327 311 cerr << args[i] << " "; 328 312 } // for … … 377 361 #ifdef __DEBUG_H__ 378 362 cerr << "cfa-cpp ncargs: " << o_name << " " << CFA_flag << " " << ncargs << endl; 379 for ( i = 0; cargs[i] != NULL; i += 1 ) {363 for ( int i = 0; cargs[i] != NULL; i += 1 ) { 380 364 cerr << cargs[i] << " "; 381 365 } // for … … 407 391 408 392 void Stage2( const int argc, const char * const * argv ) { 409 int i;410 411 393 string arg; 412 394 … … 419 401 cerr << "Stage2" << endl; 420 402 #endif // __DEBUG_H__ 403 checkEnv( args, nargs ); // arguments passed via environment variables 404 #ifdef __DEBUG_H__ 405 for ( int i = 1; i < argc; i += 1 ) { 406 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; 407 } // for 408 #endif // __DEBUG_H__ 421 409 422 410 // process all the arguments 423 411 424 checkEnv( args, nargs ); // arguments passed via environment variables 425 426 for ( i = 1; i < argc; i += 1 ) { 427 #ifdef __DEBUG_H__ 428 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; 429 #endif // __DEBUG_H__ 412 for ( int i = 1; i < argc; i += 1 ) { 430 413 arg = argv[i]; 431 #ifdef __DEBUG_H__432 cerr << "arg:\"" << arg << "\"" << endl;433 #endif // __DEBUG_H__434 414 if ( prefix( arg, "-" ) ) { 435 415 // strip inappropriate flags … … 476 456 #ifdef __DEBUG_H__ 477 457 cerr << "args:"; 478 for ( i = 1; i < nargs; i += 1 ) {458 for ( int i = 1; i < nargs; i += 1 ) { 479 459 cerr << " " << args[i]; 480 460 } // for … … 492 472 #ifdef __DEBUG_H__ 493 473 cerr << "stage2 nargs: " << nargs << endl; 494 for ( i = 0; args[i] != NULL; i += 1 ) {474 for ( int i = 0; args[i] != NULL; i += 1 ) { 495 475 cerr << args[i] << " "; 496 476 } // for … … 506 486 int main( const int argc, const char * const argv[], __attribute__((unused)) const char * const env[] ) { 507 487 #ifdef __DEBUG_H__ 508 for ( int i = 0; env[i] != NULL; i += 1 ) {488 for ( int int i = 0; env[i] != NULL; i += 1 ) { 509 489 cerr << env[i] << endl; 510 490 } // for -
driver/cfa.cc
r0cf9ffd rbedb40e 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 23 15:41:55201813 // Update Count : 27 012 // Last Modified On : Mon Sep 3 16:47:59 2018 13 // Update Count : 275 14 14 // 15 15 … … 43 43 const string suffixes[NumSuffixes] = { "cfa", "hfa", }; 44 44 45 voidsuffix( string arg, const char * args[], int & nargs ) {45 bool suffix( string arg, const char * args[], int & nargs ) { 46 46 //std::cerr << arg << std::endl; 47 47 size_t dot = arg.find_last_of( "." ); 48 48 //std::cerr << dot << " " << (dot != string::npos ? arg.substr( dot + 1 ) : "fred" ) << std::endl; 49 if ( dot == string::npos ) return ;49 if ( dot == string::npos ) return false; 50 50 string sx = arg.substr( dot + 1 ); 51 51 for ( int i = 0; i < NumSuffixes; i += 1 ) { … … 55 55 args[nargs] = "c"; 56 56 nargs += 1; 57 return ;57 return true; 58 58 } // if 59 59 } // for 60 return false; 60 61 } // suffix 61 62 … … 128 129 #ifdef __DEBUG_H__ 129 130 cerr << "CFA:" << endl; 131 for ( int i = 1; i < argc; i += 1 ) { 132 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl; 133 } // for 130 134 #endif // __DEBUG_H__ 131 135 … … 133 137 134 138 for ( int i = 1; i < argc; i += 1 ) { 135 #ifdef __DEBUG_H__136 cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;137 #endif // __DEBUG_H__138 139 arg = argv[i]; // convert to string value 139 #ifdef __DEBUG_H__140 cerr << "arg:\"" << arg << "\"" << endl;141 #endif // __DEBUG_H__142 140 if ( prefix( arg, "-" ) ) { 143 141 // pass through arguments … … 202 200 args[nargs] = argv[i]; // pass the argument along 203 201 nargs += 1; 204 } else if ( arg == "-x" ) {205 xflag = true;206 args[nargs] = argv[i]; // pass the argument along207 nargs += 1;208 i += 1; // advance to argument209 args[nargs] = argv[i]; // pass the argument along210 nargs += 1;211 // args[nargs] = ( *new string( string("-D__GCC_X__=") + argv[i] ) ).c_str(); // add the argument for -x212 // nargs += 1;213 } else if ( prefix( arg, "-x" ) ) {214 xflag = true;215 args[nargs] = argv[i]; // pass the argument along216 nargs += 1;217 // args[nargs] = ( *new string( string("-D__GCC_X__=") + arg.substr(2) ) ).c_str(); // add the argument for -x218 // nargs += 1;219 202 } else if ( arg == "-w" ) { 220 203 args[nargs] = argv[i]; // pass the argument along … … 298 281 } // if 299 282 } else { 300 bool opt = false; 301 if ( ! xflag ) { 302 suffix( arg, args, nargs ); // check suffix 303 // args[nargs] = ( *new string( string("-D__GCC_X__=c") ) ).c_str(); // add the argument for -x 304 // nargs += 1; 305 opt = true; 306 } // if 307 // concatenate other arguments 308 args[nargs] = argv[i]; 283 bool cfa = suffix( arg, args, nargs ); // check suffix 284 args[nargs] = argv[i]; // concatenate file 309 285 nargs += 1; 310 if ( opt) {286 if ( cfa ) { 311 287 args[nargs] = "-x"; 312 288 nargs += 1; 313 289 args[nargs] = "none"; 314 290 nargs += 1; 315 // args[nargs] = ( *new string( string("-D__GCC_X__=none") ) ).c_str(); // add the argument for -x316 // nargs += 1;317 291 } // if 318 292 nonoptarg = true; … … 320 294 } // if 321 295 } // for 296 297 args[nargs] = "-x"; // turn off language 298 nargs += 1; 299 args[nargs] = "none"; 300 nargs += 1; 322 301 323 302 #ifdef __x86_64__ -
libcfa/src/heap.cfa
r0cf9ffd rbedb40e 1 // #comment TD : this file uses both spaces and tabs for indentation2 3 1 // 4 2 // Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo … … 12 10 // Created On : Tue Dec 19 21:58:35 2017 13 11 // Last Modified By : Peter A. Buhr 14 // Last Modified On : Sat Aug 11 08:22:16201815 // Update Count : 49512 // Last Modified On : Thu Sep 6 09:01:30 2018 13 // Update Count : 513 16 14 // 17 15 … … 25 23 26 24 // #comment TD : Many of these should be merged into math I believe 27 #include "bits/align.hfa" 28 #include "bits/defs.hfa" 29 #include "bits/locks.hfa" 25 #include "bits/align.hfa" // libPow2 26 #include "bits/defs.hfa" // likely, unlikely 27 #include "bits/locks.hfa" // __spinlock_t 30 28 #include "startup.hfa" // STARTUP_PRIORITY_MEMORY 31 #include "stdlib.hfa" 29 #include "stdlib.hfa" // bsearchl 32 30 #include "malloc.h" 33 31 … … 151 149 152 150 extern "C" { 153 void heapAppStart() {// called by __cfaabi_appready_startup154 allocFree = 0;155 } // heapAppStart156 157 void heapAppStop() {// called by __cfaabi_appready_startdown158 fclose( stdin ); fclose( stdout );159 checkUnfreed();160 } // heapAppStop151 void heapAppStart() { // called by __cfaabi_appready_startup 152 allocFree = 0; 153 } // heapAppStart 154 155 void heapAppStop() { // called by __cfaabi_appready_startdown 156 fclose( stdin ); fclose( stdout ); 157 checkUnfreed(); 158 } // heapAppStop 161 159 } // extern "C" 162 160 #endif // __CFA_DEBUG__ … … 167 165 168 166 struct Storage { 169 167 struct Header { // header 170 168 union Kind { 171 169 struct RealHeader { 172 170 union { 173 // #comment TD : this code use byte size but the comment uses bit size 174 175 struct { // 32-bit word => 64-bit header, 64-bit word => 128-bit header 171 struct { // 4-byte word => 8-byte header, 8-byte word => 16-byte header 176 172 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4 177 173 uint32_t padding; // unused, force home/blocksize to overlay alignment in fake header 178 #endif // __ ORDER_BIG_ENDIAN__ && __U_WORDSIZE__ == 32174 #endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_POINTER__ == 4 179 175 180 176 union { … … 189 185 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4 190 186 uint32_t padding; // unused, force home/blocksize to overlay alignment in fake header 191 #endif // __ORDER_LITTLE_ENDIAN__ && __U_WORDSIZE__ == 32 192 187 #endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_POINTER__ == 4 193 188 }; 194 195 // #comment TD : C++ code 189 // future code 196 190 #if BUCKLOCK == LOCKFREE 197 191 Stack<Storage>::Link next; // freed block points next freed block of same size (double-wide) … … 211 205 } fake; // FakeHeader 212 206 } kind; // Kind 213 214 215 207 } header; // Header 208 char pad[ALIGN - sizeof( Header )]; 209 char data[0]; // storage 216 210 }; // Storage 217 211 … … 220 214 struct FreeHeader { 221 215 #if BUCKLOCK == SPINLOCK 222 223 216 __spinlock_t lock; // must be first field for alignment 217 Storage * freeList; 224 218 #elif BUCKLOCK == LOCKFREE 225 // #comment TD : C++code226 219 // future code 220 StackLF<Storage> freeList; 227 221 #else 228 222 #error undefined lock type for bucket lock 229 223 #endif // SPINLOCK 230 224 size_t blockSize; // size of allocations on this list 231 225 }; // FreeHeader 232 226 … … 249 243 static unsigned int maxBucketsUsed; // maximum number of buckets in use 250 244 251 // #comment TD : This array is not const but it feels like it should be252 245 // Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size. 253 static unsigned int bucketSizes[NoBucketSizes] @= {// different bucket sizes246 static const unsigned int bucketSizes[NoBucketSizes] @= { // different bucket sizes 254 247 16, 32, 48, 64, 255 248 64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224, … … 279 272 // #comment TD : The return type of this function should be commented 280 273 static inline bool setMmapStart( size_t value ) { 281 274 if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true; 282 275 mmapStart = value; // set global 283 276 … … 313 306 sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment 314 307 heapBegin = heapEnd = sbrk( 0 ); // get new start point 315 } // HeapManager308 } // HeapManager 316 309 317 310 … … 323 316 // } // if 324 317 #endif // __STATISTICS__ 325 } // ~HeapManager318 } // ~HeapManager 326 319 327 320 … … 329 322 void memory_startup( void ) { 330 323 #ifdef __CFA_DEBUG__ 331 if ( unlikely( heapBoot ) ) { // check for recursion during system boot324 if ( unlikely( heapBoot ) ) { // check for recursion during system boot 332 325 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT. 333 326 abort( "boot() : internal error, recursively invoked during system boot." ); … … 336 329 #endif // __CFA_DEBUG__ 337 330 338 // #comment TD : This assertion seems redundent with the above code339 assert( heapManager.heapBegin == 0 );340 heapManager{};331 //assert( heapManager.heapBegin != 0 ); 332 //heapManager{}; 333 if ( heapManager.heapBegin == 0 ) heapManager{}; 341 334 } // memory_startup 342 335 … … 374 367 char helpText[512]; 375 368 __cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText), 376 "\nHeap statistics:\n"377 " malloc: calls %u / storage %llu\n"378 " calloc: calls %u / storage %llu\n"379 " memalign: calls %u / storage %llu\n"380 " cmemalign: calls %u / storage %llu\n"381 " realloc: calls %u / storage %llu\n"382 " free: calls %u / storage %llu\n"383 " mmap: calls %u / storage %llu\n"384 " munmap: calls %u / storage %llu\n"385 " sbrk: calls %u / storage %llu\n",386 malloc_calls, malloc_storage,387 calloc_calls, calloc_storage,388 memalign_calls, memalign_storage,389 cmemalign_calls, cmemalign_storage,390 realloc_calls, realloc_storage,391 free_calls, free_storage,392 mmap_calls, mmap_storage,393 munmap_calls, munmap_storage,394 sbrk_calls, sbrk_storage369 "\nHeap statistics:\n" 370 " malloc: calls %u / storage %llu\n" 371 " calloc: calls %u / storage %llu\n" 372 " memalign: calls %u / storage %llu\n" 373 " cmemalign: calls %u / storage %llu\n" 374 " realloc: calls %u / storage %llu\n" 375 " free: calls %u / storage %llu\n" 376 " mmap: calls %u / storage %llu\n" 377 " munmap: calls %u / storage %llu\n" 378 " sbrk: calls %u / storage %llu\n", 379 malloc_calls, malloc_storage, 380 calloc_calls, calloc_storage, 381 memalign_calls, memalign_storage, 382 cmemalign_calls, cmemalign_storage, 383 realloc_calls, realloc_storage, 384 free_calls, free_storage, 385 mmap_calls, mmap_storage, 386 munmap_calls, munmap_storage, 387 sbrk_calls, sbrk_storage 395 388 ); 396 389 } // printStats 397 390 398 // #comment TD : Why do we have this? 399 static int printStatsXML( FILE * stream ) { 391 static int printStatsXML( FILE * stream ) { // see malloc_info 400 392 char helpText[512]; 401 393 int len = snprintf( helpText, sizeof(helpText), … … 431 423 static inline void noMemory() { 432 424 abort( "Heap memory exhausted at %zu bytes.\n" 433 434 425 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.", 426 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) ); 435 427 } // noMemory 436 428 … … 444 436 445 437 static inline bool setHeapExpand( size_t value ) { 446 438 if ( heapExpand < pageSize ) return true; 447 439 heapExpand = value; 448 440 return false; … … 453 445 if ( unlikely( check ) ) { // bad address ? 454 446 abort( "Attempt to %s storage %p with address outside the heap.\n" 455 456 447 "Possible cause is duplicate free on same block or overwriting of memory.", 448 name, addr ); 457 449 } // if 458 450 } // checkHeader … … 484 476 485 477 #ifdef __CFA_DEBUG__ 486 478 checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ? 487 479 #endif // __CFA_DEBUG__ 488 480 … … 490 482 // It's called as the first statement of both branches of the last if, with the same parameters in all cases 491 483 492 493 484 // header may be safe to dereference 485 fakeHeader( header, size, alignment ); 494 486 #ifdef __CFA_DEBUG__ 495 487 checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -) 496 488 #endif // __CFA_DEBUG__ 497 489 498 490 freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3); 499 491 #ifdef __CFA_DEBUG__ 500 501 502 503 504 492 if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) { 493 abort( "Attempt to %s storage %p with corrupted header.\n" 494 "Possible cause is duplicate free on same block or overwriting of header information.", 495 name, addr ); 496 } // if 505 497 #endif // __CFA_DEBUG__ 506 507 498 size = freeElem->blockSize; 499 return false; 508 500 } // headers 509 501 … … 521 513 return 0; 522 514 } // if 523 #ifdef __STATISTICS__515 #ifdef __STATISTICS__ 524 516 sbrk_calls += 1; 525 517 sbrk_storage += increase; 526 #endif // __STATISTICS__527 #ifdef __CFA_DEBUG__518 #endif // __STATISTICS__ 519 #ifdef __CFA_DEBUG__ 528 520 // Set new memory to garbage so subsequent uninitialized usages might fail. 529 521 memset( (char *)heapEnd + heapRemaining, '\377', increase ); 530 #endif // __CFA_DEBUG__522 #endif // __CFA_DEBUG__ 531 523 rem = heapRemaining + increase - size; 532 524 } // if … … 560 552 561 553 #if defined( SPINLOCK ) 562 563 554 lock( freeElem->lock __cfaabi_dbg_ctx2 ); 555 block = freeElem->freeList; // remove node from stack 564 556 #else 565 557 block = freeElem->freeList.pop(); 566 558 #endif // SPINLOCK 567 559 if ( unlikely( block == 0 ) ) { // no free block ? … … 569 561 unlock( freeElem->lock ); 570 562 #endif // SPINLOCK 563 571 564 // Freelist for that size was empty, so carve it out of the heap if there's enough left, or get some more 572 565 // and then carve it off. 573 566 574 567 block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call 575 568 if ( unlikely( block == 0 ) ) return 0; 576 569 #if defined( SPINLOCK ) 577 570 } else { … … 582 575 583 576 block->header.kind.real.home = freeElem; // pointer back to free list of apropriate size 584 577 } else { // large size => mmap 585 578 tsize = libCeiling( tsize, pageSize ); // must be multiple of page size 586 579 #ifdef __STATISTICS__ 587 588 580 __atomic_add_fetch( &mmap_calls, 1, __ATOMIC_SEQ_CST ); 581 __atomic_add_fetch( &mmap_storage, tsize, __ATOMIC_SEQ_CST ); 589 582 #endif // __STATISTICS__ 590 583 block = (HeapManager.Storage *)mmap( 0, tsize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, mmapFd, 0 ); … … 593 586 abort( "(HeapManager &)0x%p.doMalloc() : internal error, mmap failure, size:%zu error:%d.", &heapManager, tsize, errno ); 594 587 } // if 595 #ifdef __CFA_DEBUG__588 #ifdef __CFA_DEBUG__ 596 589 // Set new memory to garbage so subsequent uninitialized usages might fail. 597 590 memset( block, '\377', tsize ); 598 #endif // __CFA_DEBUG__591 #endif // __CFA_DEBUG__ 599 592 block->header.kind.real.blockSize = tsize; // storage size for munmap 600 601 602 593 } // if 594 595 void * area = &(block->data); // adjust off header to user bytes 603 596 604 597 #ifdef __CFA_DEBUG__ 605 606 607 608 609 610 611 612 613 598 assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ? 599 __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST ); 600 if ( traceHeap() ) { 601 enum { BufferSize = 64 }; 602 char helpText[BufferSize]; 603 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize ); 604 // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size ); 605 __cfaabi_dbg_bits_write( helpText, len ); 606 } // if 614 607 #endif // __CFA_DEBUG__ 615 608 … … 620 613 static inline void doFree( void * addr ) with ( heapManager ) { 621 614 #ifdef __CFA_DEBUG__ 622 623 624 615 if ( unlikely( heapManager.heapBegin == 0 ) ) { 616 abort( "doFree( %p ) : internal error, called before heap is initialized.", addr ); 617 } // if 625 618 #endif // __CFA_DEBUG__ 626 619 … … 631 624 if ( headers( "free", addr, header, freeElem, size, alignment ) ) { // mmapped ? 632 625 #ifdef __STATISTICS__ 633 634 626 __atomic_add_fetch( &munmap_calls, 1, __ATOMIC_SEQ_CST ); 627 __atomic_add_fetch( &munmap_storage, size, __ATOMIC_SEQ_CST ); 635 628 #endif // __STATISTICS__ 636 629 if ( munmap( header, size ) == -1 ) { 637 630 #ifdef __CFA_DEBUG__ 638 631 abort( "Attempt to deallocate storage %p not allocated or with corrupt header.\n" 639 640 632 "Possible cause is invalid pointer.", 633 addr ); 641 634 #endif // __CFA_DEBUG__ 642 635 } // if 643 636 } else { 644 637 #ifdef __CFA_DEBUG__ 645 646 638 // Set free memory to garbage so subsequent usages might fail. 639 memset( ((HeapManager.Storage *)header)->data, '\377', freeElem->blockSize - sizeof( HeapManager.Storage ) ); 647 640 #endif // __CFA_DEBUG__ 648 641 649 642 #ifdef __STATISTICS__ 650 643 free_storage += size; 651 644 #endif // __STATISTICS__ 652 645 #if defined( SPINLOCK ) 653 654 655 656 646 lock( freeElem->lock __cfaabi_dbg_ctx2 ); // acquire spin lock 647 header->kind.real.next = freeElem->freeList; // push on stack 648 freeElem->freeList = (HeapManager.Storage *)header; 649 unlock( freeElem->lock ); // release spin lock 657 650 #else 658 651 freeElem->freeList.push( *(HeapManager.Storage *)header ); 659 652 #endif // SPINLOCK 660 653 } // if 661 654 662 655 #ifdef __CFA_DEBUG__ 663 664 665 666 667 668 656 __atomic_add_fetch( &allocFree, -size, __ATOMIC_SEQ_CST ); 657 if ( traceHeap() ) { 658 char helpText[64]; 659 int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size ); 660 __cfaabi_dbg_bits_write( helpText, len ); 661 } // if 669 662 #endif // __CFA_DEBUG__ 670 663 } // doFree … … 674 667 size_t total = 0; 675 668 #ifdef __STATISTICS__ 676 677 669 __cfaabi_dbg_bits_acquire(); 670 __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" ); 678 671 #endif // __STATISTICS__ 679 672 for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) { … … 695 688 696 689 #ifdef __STATISTICS__ 697 698 690 __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u ", size, N ); 691 if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" ); 699 692 #endif // __STATISTICS__ 700 693 } // for 701 694 #ifdef __STATISTICS__ 702 703 695 __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total ); 696 __cfaabi_dbg_bits_release(); 704 697 #endif // __STATISTICS__ 705 698 return (char *)heapEnd - (char *)heapBegin - total; 706 699 } // checkFree 707 700 708 // #comment TD : This is not a good name, plus this feels like it could easily be folded into doMalloc 709 static inline void * malloc2( size_t size ) { // necessary for malloc statistics 710 assert( heapManager.heapBegin != 0 ); 701 702 static inline void * mallocNoStats( size_t size ) { // necessary for malloc statistics 703 //assert( heapManager.heapBegin != 0 ); 704 if ( unlikely( heapManager.heapBegin == 0 ) ) heapManager{}; // called before memory_startup ? 711 705 void * area = doMalloc( size ); 712 706 if ( unlikely( area == 0 ) ) errno = ENOMEM; // POSIX 713 707 return area; 714 } // malloc 2715 716 717 static inline void * memalign 2( size_t alignment, size_t size ) { // necessary for malloc statistics718 #ifdef __CFA_DEBUG__708 } // mallocNoStats 709 710 711 static inline void * memalignNoStats( size_t alignment, size_t size ) { // necessary for malloc statistics 712 #ifdef __CFA_DEBUG__ 719 713 checkAlign( alignment ); // check alignment 720 #endif // __CFA_DEBUG__714 #endif // __CFA_DEBUG__ 721 715 722 716 // if alignment <= default alignment, do normal malloc as two headers are unnecessary 723 if ( unlikely( alignment <= libAlign() ) ) return malloc2( size );717 if ( unlikely( alignment <= libAlign() ) ) return mallocNoStats( size ); 724 718 725 719 // Allocate enough storage to guarantee an address on the alignment boundary, and sufficient space before it for … … 732 726 // subtract libAlign() because it is already the minimum alignment 733 727 // add sizeof(Storage) for fake header 734 // #comment TD : this is the only place that calls doMalloc without calling malloc 2, why ?728 // #comment TD : this is the only place that calls doMalloc without calling mallocNoStats, why ? 735 729 char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) ); 736 730 if ( unlikely( area == 0 ) ) return area; 737 731 738 732 // address in the block of the "next" alignment address … … 749 743 750 744 return user; 751 } // memalign 2745 } // memalignNoStats 752 746 753 747 754 748 extern "C" { 755 // The malloc() function allocates size bytes and returns a pointer to the 756 // allocated memory. The memory is not initialized. If size is 0, then malloc() 757 // returns either NULL, or a unique pointer value that can later be successfully 758 // passed to free(). 749 // The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not 750 // initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be 751 // successfully passed to free(). 759 752 void * malloc( size_t size ) { 760 753 #ifdef __STATISTICS__ 761 __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST ); 762 __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST ); 763 #endif // __STATISTICS__ 764 765 return malloc2( size ); 766 } // malloc 767 768 // The calloc() function allocates memory for an array of nmemb elements of 769 // size bytes each and returns a pointer to the allocated memory. The memory 770 // is set to zero. If nmemb or size is 0, then calloc() returns either NULL, 771 // or a unique pointer value that can later be successfully passed to free(). 772 void * calloc( size_t noOfElems, size_t elemSize ) { 754 __atomic_add_fetch( &malloc_calls, 1, __ATOMIC_SEQ_CST ); 755 __atomic_add_fetch( &malloc_storage, size, __ATOMIC_SEQ_CST ); 756 #endif // __STATISTICS__ 757 758 return mallocNoStats( size ); 759 } // malloc 760 761 // The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to 762 // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a 763 // unique pointer value that can later be successfully passed to free(). 764 void * calloc( size_t noOfElems, size_t elemSize ) { 773 765 size_t size = noOfElems * elemSize; 774 766 #ifdef __STATISTICS__ 775 776 777 #endif // __STATISTICS__ 778 779 char * area = (char *)malloc 2( size );780 767 __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST ); 768 __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST ); 769 #endif // __STATISTICS__ 770 771 char * area = (char *)mallocNoStats( size ); 772 if ( unlikely( area == 0 ) ) return 0; 781 773 782 774 HeapManager.Storage.Header * header; … … 790 782 memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros 791 783 792 header->kind.real.blockSize |= 2; // mark as zero filled784 header->kind.real.blockSize |= 2; // mark as zero filled 793 785 return area; 794 786 } // calloc 795 787 796 788 // #comment TD : Document this function … … 798 790 size_t size = noOfElems * elemSize; 799 791 #ifdef __STATISTICS__ 800 801 802 #endif // __STATISTICS__ 803 804 char * area = (char *)memalign 2( alignment, size );805 792 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST ); 793 __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST ); 794 #endif // __STATISTICS__ 795 796 char * area = (char *)memalignNoStats( alignment, size ); 797 if ( unlikely( area == 0 ) ) return 0; 806 798 HeapManager.Storage.Header * header; 807 799 HeapManager.FreeHeader * freeElem; … … 811 803 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 812 804 if ( ! mapped ) 813 #endif // __CFA_DEBUG__805 #endif // __CFA_DEBUG__ 814 806 memset( area, '\0', asize - ( (char *)area - (char *)header ) ); // set to zeros 815 807 header->kind.real.blockSize |= 2; // mark as zero filled 816 808 817 809 return area; 818 } // cmemalign 819 820 // The realloc() function changes the size of the memory block pointed to by 821 // ptr to size bytes. The contents will be unchanged in the range from the 822 // start of the region up to the minimum of the old and new sizes. If the new 823 // size is larger than the old size, the added memory will not be initialized. 824 // If ptr is NULL, then the call is equivalent to malloc(size), for all values 825 // of size; if size is equal to zero, and ptr is not NULL, then the call is 826 // equivalent to free(ptr). Unless ptr is NULL, it must have been returned by 827 // an earlier call to malloc(), calloc() or realloc(). If the area pointed to 828 // was moved, a free(ptr) is done. 829 void * realloc( void * addr, size_t size ) { 830 #ifdef __STATISTICS__ 831 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 832 #endif // __STATISTICS__ 833 834 if ( unlikely( addr == 0 ) ) return malloc2( size ); // special cases 835 if ( unlikely( size == 0 ) ) { free( addr ); return 0; } 810 } // cmemalign 811 812 // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be 813 // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size 814 // is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the call is 815 // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call 816 // is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), 817 // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done. 818 void * realloc( void * addr, size_t size ) { 819 #ifdef __STATISTICS__ 820 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST ); 821 #endif // __STATISTICS__ 822 823 if ( unlikely( addr == 0 ) ) return mallocNoStats( size ); // special cases 824 if ( unlikely( size == 0 ) ) { free( addr ); return 0; } 836 825 837 826 HeapManager.Storage.Header * header; … … 848 837 849 838 #ifdef __STATISTICS__ 850 839 __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST ); 851 840 #endif // __STATISTICS__ 852 841 … … 855 844 area = memalign( alignment, size ); // create new area 856 845 } else { 857 area = malloc 2( size );// create new area846 area = mallocNoStats( size ); // create new area 858 847 } // if 859 848 if ( unlikely( area == 0 ) ) return 0; 860 849 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill (calloc/cmemalign) ? 861 850 assert( (header->kind.real.blockSize & 1) == 0 ); … … 864 853 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero. 865 854 if ( ! mapped ) 866 #endif // __CFA_DEBUG__855 #endif // __CFA_DEBUG__ 867 856 memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part 868 857 header->kind.real.blockSize |= 2; // mark new request as zero fill … … 874 863 875 864 876 // The obsolete function memalign() allocates size bytes and returns 877 // a pointer to the allocated memory. The memory address will be a 878 // multiple of alignment, which must be a power of two. 879 void * memalign( size_t alignment, size_t size ) __attribute__ ((deprecated)); 880 void * memalign( size_t alignment, size_t size ) { 865 // The obsolete function memalign() allocates size bytes and returns a pointer to the allocated memory. The memory 866 // address will be a multiple of alignment, which must be a power of two. 867 void * memalign( size_t alignment, size_t size ) { 881 868 #ifdef __STATISTICS__ 882 869 __atomic_add_fetch( &memalign_calls, 1, __ATOMIC_SEQ_CST ); … … 884 871 #endif // __STATISTICS__ 885 872 886 void * area = memalign 2( alignment, size );873 void * area = memalignNoStats( alignment, size ); 887 874 888 875 return area; 889 890 891 // The function aligned_alloc() is the same as memalign(), except for 892 // the added restriction that size should be amultiple of alignment.876 } // memalign 877 878 // The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a 879 // multiple of alignment. 893 880 void * aligned_alloc( size_t alignment, size_t size ) { 894 881 return memalign( alignment, size ); … … 896 883 897 884 898 // The function posix_memalign() allocates size bytes and places the address 899 // of the allocated memory in *memptr. The address of the allocated memory 900 // will be a multiple of alignment, which must be a power of two and a multiple 901 // of sizeof(void *). If size is 0, then posix_memalign() returns either NULL, 902 // or a unique pointer value that can later be successfully passed to free(3). 885 // The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The 886 // address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of 887 // sizeof(void *). If size is 0, then posix_memalign() returns either NULL, or a unique pointer value that can later 888 // be successfully passed to free(3). 903 889 int posix_memalign( void ** memptr, size_t alignment, size_t size ) { 904 890 if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment 905 891 * memptr = memalign( alignment, size ); 906 892 if ( unlikely( * memptr == 0 ) ) return ENOMEM; 907 893 return 0; 908 894 } // posix_memalign 909 895 910 // The obsolete function valloc() allocates size bytes and returns a pointer 911 // to the allocated memory. The memory address will be a multiple of the page size. 912 // It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 913 void * valloc( size_t size ) __attribute__ ((deprecated)); 896 // The obsolete function valloc() allocates size bytes and returns a pointer to the allocated memory. The memory 897 // address will be a multiple of the page size. It is equivalent to memalign(sysconf(_SC_PAGESIZE),size). 914 898 void * valloc( size_t size ) { 915 899 return memalign( pageSize, size ); … … 917 901 918 902 919 // The free() function frees the memory space pointed to by ptr, which must 920 // have been returned by a previous call to malloc(), calloc() or realloc(). 921 // Otherwise, or if free(ptr) has already been called before, undefined 922 // behavior occurs. If ptr is NULL, no operation is performed. 903 // The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to 904 // malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior 905 // occurs. If ptr is NULL, no operation is performed. 923 906 void free( void * addr ) { 924 907 #ifdef __STATISTICS__ 925 908 __atomic_add_fetch( &free_calls, 1, __ATOMIC_SEQ_CST ); 926 909 #endif // __STATISTICS__ 927 910 … … 931 914 if ( unlikely( addr == 0 ) ) { // special case 932 915 #ifdef __CFA_DEBUG__ 933 934 935 936 937 916 if ( traceHeap() ) { 917 #define nullmsg "Free( 0x0 ) size:0\n" 918 // Do not debug print free( 0 ), as it can cause recursive entry from sprintf. 919 __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 ); 920 } // if 938 921 #endif // __CFA_DEBUG__ 939 922 return; … … 943 926 } // free 944 927 945 // The mallopt() function adjusts parameters that control the behavior of the 946 // memory-allocation functions (see malloc(3)). The param argument specifies 947 // the parameter to be modified, and value specifies the new value for that 928 // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see 929 // malloc(3)). The param argument specifies the parameter to be modified, and value specifies the new value for that 948 930 // parameter. 949 931 int mallopt( int option, int value ) { 950 932 choose( option ) { 951 952 953 954 955 956 957 933 case M_TOP_PAD: 934 if ( setHeapExpand( value ) ) fallthru default; 935 case M_MMAP_THRESHOLD: 936 if ( setMmapStart( value ) ) fallthru default; 937 default: 938 // #comment TD : 1 for unsopported feels wrong 939 return 1; // success, or unsupported 958 940 } // switch 959 941 return 0; // error 960 942 } // mallopt 961 943 962 // The malloc_trim() function attempts to release free memory at the top 963 // of the heap (by calling sbrk(2) with asuitable argument).944 // The malloc_trim() function attempts to release free memory at the top of the heap (by calling sbrk(2) with a 945 // suitable argument). 964 946 int malloc_trim( size_t ) { 965 947 return 0; // => impossible to release memory 966 948 } // malloc_trim 967 949 968 // The malloc_usable_size() function returns the number of usable bytes in the 969 // block pointed to by ptr, a pointer to a block of memory allocated by 970 // malloc(3) or a related function. 971 size_t malloc_usable_size( void * addr ) { 972 if ( unlikely( addr == 0 ) ) return 0; // null allocation has 0 size 950 // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to 951 // a block of memory allocated by malloc(3) or a related function. 952 size_t malloc_usable_size( void * addr ) { 953 if ( unlikely( addr == 0 ) ) return 0; // null allocation has 0 size 973 954 974 955 HeapManager.Storage.Header * header; … … 982 963 983 964 984 // #comment TD : Document this function 965 // The malloc_alignment() function returns the alignment of the allocation. 985 966 size_t malloc_alignment( void * addr ) { 986 967 if ( unlikely( addr == 0 ) ) return libAlign(); // minimum alignment 987 968 HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ); 988 969 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ? … … 991 972 return libAlign (); // minimum alignment 992 973 } // if 993 994 995 996 // #comment TD : Document this function 974 } // malloc_alignment 975 976 977 // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc(). 997 978 bool malloc_zero_fill( void * addr ) { 998 979 if ( unlikely( addr == 0 ) ) return false; // null allocation is not zero fill 999 980 1000 981 HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ); … … 1003 984 } // if 1004 985 return (header->kind.real.blockSize & 2) != 0; // zero filled (calloc/cmemalign) ? 1005 } // malloc_zero_fill 1006 1007 1008 // #comment TD : Document this function 986 } // malloc_zero_fill 987 988 989 // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and 990 // related functions. 1009 991 void malloc_stats( void ) { 1010 992 #ifdef __STATISTICS__ 1011 1012 1013 #endif // __STATISTICS__ 1014 1015 1016 // #comment TD : Document this function1017 1018 #ifdef __STATISTICS__ 1019 1020 1021 993 printStats(); 994 if ( checkFree() ) checkFree( heapManager ); 995 #endif // __STATISTICS__ 996 } // malloc_stats 997 998 // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics. 999 int malloc_stats_fd( int fd ) { 1000 #ifdef __STATISTICS__ 1001 int temp = statfd; 1002 statfd = fd; 1003 return temp; 1022 1004 #else 1023 return -1; 1024 #endif // __STATISTICS__ 1025 } // malloc_stats_fd 1026 1027 1028 // #comment TD : Document this function 1005 return -1; 1006 #endif // __STATISTICS__ 1007 } // malloc_stats_fd 1008 1009 // The malloc_info() function exports an XML string that describes the current state of the memory-allocation 1010 // implementation in the caller. The string is printed on the file stream stream. The exported string includes 1011 // information about all arenas (see malloc(3)). 1029 1012 int malloc_info( int options, FILE * stream ) { 1030 1013 return printStatsXML( stream ); … … 1032 1015 1033 1016 1034 // #comment TD : What are these two functions for? 1017 // The malloc_get_state() function records the current state of all malloc(3) internal bookkeeping variables (but 1018 // not the actual contents of the heap or the state of malloc_hook(3) functions pointers). The state is recorded in 1019 // a system-dependent opaque data structure dynamically allocated via malloc(3), and a pointer to that data 1020 // structure is returned as the function result. (It is the caller's responsibility to free(3) this memory.) 1035 1021 void * malloc_get_state( void ) { 1036 return 0; 1022 return 0; // unsupported 1037 1023 } // malloc_get_state 1038 1024 1025 1026 // The malloc_set_state() function restores the state of all malloc(3) internal bookkeeping variables to the values 1027 // recorded in the opaque data structure pointed to by state. 1039 1028 int malloc_set_state( void * ptr ) { 1040 return 0; 1029 return 0; // unsupported 1041 1030 } // malloc_set_state 1042 1031 } // extern "C" -
src/Parser/lex.ll
r0cf9ffd rbedb40e 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Wed Aug 8 17:23:17201813 * Update Count : 68 512 * Last Modified On : Wed Aug 29 15:02:41 2018 13 * Update Count : 686 14 14 */ 15 15 … … 410 410 ">>=" { NAMEDOP_RETURN(RSassign); } 411 411 412 "~=" { NAMEDOP_RETURN(Erange); } // CFA413 412 "@=" { NAMEDOP_RETURN(ATassign); } // CFA 413 "~=" { NAMEDOP_RETURN(ErangeUpEq); } // CFA 414 "-~" { NAMEDOP_RETURN(ErangeDown); } // CFA 415 "-~=" { NAMEDOP_RETURN(ErangeDownEq); } // CFA 414 416 415 417 /* CFA, operator identifier */ -
src/Parser/parser.yy
r0cf9ffd rbedb40e 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Aug 8 17:50:07201813 // Update Count : 399812 // Last Modified On : Thu Aug 30 17:02:25 2018 13 // Update Count : 4029 14 14 // 15 15 … … 186 186 } // fieldDecl 187 187 188 ExpressionNode *forInc( const OperKinds op ) { 189 return new ExpressionNode( build_constantInteger( *new string( op == OperKinds::LThan || op == OperKinds::LEThan ? "1" : "-1" ) ) ); 190 } // forInc 191 188 192 ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 193 ConstantExpr *constant = dynamic_cast<ConstantExpr *>(type->get_expr()); 194 if ( constant && (constant->get_constant()->get_value() == "0" || constant->get_constant()->get_value() == "1") ) { 195 type = new ExpressionNode( new CastExpr( maybeMoveBuild< Expression >(type), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ) ); 196 } // if 189 197 return new ForCtrl( 190 198 distAttr( DeclarationNode::newTypeof( type ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ), … … 214 222 215 223 // Types declaration for productions 216 %union 217 { 224 %union { 218 225 Token tok; 219 226 ParseNode * pn; … … 290 297 %token ANDassign ERassign ORassign // &= ^= |= 291 298 292 %token Erange //~=299 %token ErangeUpEq ErangeDown ErangeDownEq // ~= -~ -~= 293 300 %token ATassign // @= 294 301 … … 1138 1145 $$ = new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ); 1139 1146 } else { 1140 $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), OperKinds::LThan, $1->clone(),1141 new ExpressionNode( build_constantInteger( *new string( "1" ) )) );1147 $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1148 OperKinds::LThan, $1->clone(), forInc( OperKinds::LThan ) ); 1142 1149 } // if 1143 1150 } 1144 1151 | constant_expression inclexcl constant_expression // CFA 1145 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, new ExpressionNode( build_constantInteger( *new string( "1" ) )) ); }1152 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, forInc( $2 ) ); } 1146 1153 | constant_expression inclexcl constant_expression '~' constant_expression // CFA 1147 1154 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, $5 ); } … … 1154 1161 } else { 1155 1162 if ( NameExpr *identifier = dynamic_cast<NameExpr *>($1->get_expr()) ) { 1156 $$ = forCtrl( $3, new string( identifier->name ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), OperKinds::LThan, $3->clone(),1157 new ExpressionNode( build_constantInteger( *new string( "1" ) )) );1163 $$ = forCtrl( $3, new string( identifier->name ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1164 OperKinds::LThan, $3->clone(), forInc( OperKinds::LThan ) ); 1158 1165 } else { 1159 1166 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); $$ = nullptr; … … 1167 1174 } else { 1168 1175 if ( NameExpr *identifier = dynamic_cast<NameExpr *>($1->get_expr()) ) { 1169 $$ = forCtrl( $3, new string( identifier->name ), $3->clone(), $4, $5, new ExpressionNode( build_constantInteger( *new string( "1" ) )) );1176 $$ = forCtrl( $3, new string( identifier->name ), $3->clone(), $4, $5, forInc( $4 ) ); 1170 1177 } else { 1171 1178 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); $$ = nullptr; … … 1194 1201 '~' 1195 1202 { $$ = OperKinds::LThan; } 1196 | Erange 1203 | ErangeUpEq 1197 1204 { $$ = OperKinds::LEThan; } 1205 | ErangeDown 1206 { $$ = OperKinds::GThan; } 1207 | ErangeDownEq 1208 { $$ = OperKinds::GEThan; } 1198 1209 ; 1199 1210 -
src/SymTab/Validate.cc
r0cf9ffd rbedb40e 403 403 assert( aggr ); // TODO: need to handle forward declarations 404 404 for ( Declaration * member : aggr->members ) { 405 if ( StructInstType * inst = dynamic_cast< StructInstType * >( child ) ) { 406 if ( StructDecl * aggr = dynamic_cast< StructDecl * >( member ) ) { 407 if ( aggr->name == inst->name ) { 408 // TODO: is this case, and other non-TypeInstType cases, necessary? 409 return new StructInstType( qualType->get_qualifiers(), aggr ); 410 } 411 } 412 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( child ) ) { 413 if ( UnionDecl * aggr = dynamic_cast< UnionDecl * > ( member ) ) { 414 if ( aggr->name == inst->name ) { 415 return new UnionInstType( qualType->get_qualifiers(), aggr ); 416 } 417 } 418 } else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( child ) ) { 419 if ( EnumDecl * aggr = dynamic_cast< EnumDecl * > ( member ) ) { 420 if ( aggr->name == inst->name ) { 421 return new EnumInstType( qualType->get_qualifiers(), aggr ); 422 } 423 } 424 } else if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) { 405 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) { 425 406 // name on the right is a typedef 426 407 if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) { … … 429 410 Type * ret = aggr->base->clone(); 430 411 ret->get_qualifiers() = qualType->get_qualifiers(); 412 TypeSubstitution sub = parent->genericSubstitution(); 413 sub.apply(ret); 431 414 return ret; 432 415 } -
tests/.expect/forctrl.txt
r0cf9ffd rbedb40e 2 2 empty 3 3 empty 4 X X X X X X X X X X 5 Y Y Y Y Y 6 Z Z Z Z Z 4 5 A 6 A A 7 A A A A A A A A A A 8 B B B B B 9 C C C C C 10 D D D D D 11 E E E E E 7 12 0 1 2 3 4 5 6 7 8 9 8 13 0 1 2 3 4 5 6 7 8 9 14 1 3 5 7 9 15 10 8 6 4 2 9 16 0.5 1.5 2.5 3.5 4.5 17 5.5 4.5 3.5 2.5 1.5 10 18 2 4 6 8 10 11 2 4 6 8 10 19 10 8 6 4 2 12 20 3 6 9 13 21 (0 0)(1 1)(2 2)(3 3)(4 4)(5 5)(6 6)(7 7)(8 8)(9 9) -
tests/forctrl.c
r0cf9ffd rbedb40e 10 10 // Created On : Wed Aug 8 18:32:59 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 16 09:25:47201813 // Update Count : 612 // Last Modified On : Thu Aug 30 17:12:12 2018 13 // Update Count : 43 14 14 // 15 15 … … 33 33 do { sout | "empty"; break; } while (); sout | endl; 34 34 for () { sout | "empty"; break; } sout | endl; 35 for ( 10 ) { sout | "X"; } sout | endl; 36 for ( 0.5 ~ 5.5 ) { sout | "Y"; } sout | endl; 37 for ( 2 ~= 10 ~ 2 ) { sout | "Z"; } sout | endl; 35 36 for ( 0 ) { sout | "A"; } sout | endl; 37 for ( 1 ) { sout | "A"; } sout | endl; 38 for ( 2 ) { sout | "A"; } sout | endl; 39 for ( 10 ) { sout | "A"; } sout | endl; 40 41 for ( 1 ~= 10 ~ 2 ) { sout | "B"; } sout | endl; 42 for ( 10 -~= 1 ~ -2 ) { sout | "C"; } sout | endl; 43 for ( 0.5 ~ 5.5 ) { sout | "D"; } sout | endl; 44 for ( 5.5 -~ 0.5 ) { sout | "E"; } sout | endl; 45 38 46 for ( i; 10 ) { sout | i; } sout | endl; 39 47 for ( j; 10 ) { sout | j; } sout | endl; 48 49 for ( i; 1 ~= 10 ~ 2 ) { sout | i; } sout | endl; 50 for ( i; 10 -~= 1 ~ -2 ) { sout | i; } sout | endl; 40 51 for ( i; 0.5 ~ 5.5 ) { sout | i; } sout | endl; 41 for ( i; 2 ~= 10 ~ 2 ) { sout | i; } sout | endl; 52 for ( i; 5.5 -~ 0.5 ) { sout | i; } sout | endl; 53 42 54 for ( ui; 2u ~= 10u ~ 2u ) { sout | ui; } sout | endl; 55 for ( ui; 10u -~= 2u ~ -2u ) { sout | ui; } sout | endl; 56 43 57 int start = 3, comp = 10, inc = 2; 44 58 for ( i; start ~ comp ~ inc + 1 ) { sout | i; } sout | endl;
Note: See TracChangeset
for help on using the changeset viewer.