Changeset a554e5f4
- Timestamp:
- Feb 9, 2022, 3:33:42 PM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- 850aff1
- Parents:
- 21a99cc (diff), c4f8170 (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:
-
- 2 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.sty
r21a99cc ra554e5f4 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Mon May 31 09:08:37 202114 %% Update Count : 56 513 %% Last Modified On : Mon Feb 7 23:00:46 2022 14 %% Update Count : 569 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 43 43 \newcommand{\CCIcon}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}} % C++ icon 44 44 \newcommand{\CC}[1][]{\protect\CCIcon{#1}\xspace} % C++ symbolic name 45 \newcommand{\Cpp}[1][]{\CC{#1}} % C++ synonym 45 46 % numbers disallowed in latex variables names => use number names 46 47 \newcommand{\CCeleven}{\protect\CCIcon{11}\xspace} % C++11 symbolic name … … 51 52 52 53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 55 \usepackage{pslatex} % reduce size of san serif font 56 \usepackage{relsize} % must be after change to small or selects old size 57 \usepackage{rotating} 58 \usepackage{calc} % latex arithmetic 53 59 54 60 % remove special-character warning in PDF side-bar names … … 71 77 \newlength{\parindentlnth} 72 78 \setlength{\parindentlnth}{\parindent} 73 74 \usepackage{pslatex} % reduce size of san serif font75 \usepackage{relsize} % must be after change to small or selects old size76 \usepackage{rotating}77 \usepackage{calc} % latex arithmetic78 79 79 80 % reduce size of chapter/section titles … … 151 152 \newcommand{\@snewterm}[2][\@empty]{{\newtermFontInline{#2}}\ifx#1\@empty\index{#2}\else\index{#1@{\protect#2}}\fi} 152 153 154 % \snake{<identifier>} 155 % Improves writing of snake case (or any convention that uses _) by allowing 156 % line breaks after _. Disables commands inside the block and formats the 157 % identifier to look like code. 158 \newcommand*\snake[1]{\snakefont{\expandafter\snake@next\detokenize{#1}\@nil}} 159 160 % \snakefont{<text>} 161 % Command used by \snake, you may renew the command to change its formating. 162 \newcommand*\snakefont[1]{\LstBasicStyle{#1}} 163 164 % Thanks Manuel of TeX Stack exchange. (I got the base pattern from one of 165 % their answers.) Note: \@nil should never be defined. 166 \newcommand*\snake@next[1]{\ifx\@nil#1\else 167 \expandafter\ifx\string_#1\string_\allowbreak\else#1\fi 168 \expandafter\snake@next\fi 169 } 170 171 % \lang{<language>}{<code>} 172 % Use the listings package to format the snipit of <code> in <language>. 173 \newcommand{\lang}[2]{\lstinline[language=#1]{#2}} 174 153 175 % Latin abbreviation 154 176 \newcommand{\abbrevFont}{\textit} % set empty for no italics … … 263 285 extendedchars=true, % allow ASCII characters in the range 128-255 264 286 escapechar=\$, % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-' 265 mathescape=false, % LaTeX math escape in CFA code $...$287 mathescape=false, % disable LaTeX math escape in CFA code $...$ 266 288 keepspaces=true, % 267 289 showstringspaces=false, % do not show spaces with cup … … 308 330 }{} 309 331 % inline code @...@ (at symbol) 310 \makeatother311 332 \lstMakeShortInline@ % single-character for \lstinline 312 \makeatletter313 333 \fi% 314 334 -
doc/LaTeXmacros/common.tex
r21a99cc ra554e5f4 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Mon May 31 09:10:49 202114 %% Update Count : 5 4613 %% Last Modified On : Mon Feb 7 23:00:08 2022 14 %% Update Count : 552 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 43 43 \newcommand{\CCIcon}{\textrm{C}\kern-.1em\hbox{+\kern-.25em+}} % C++ icon 44 44 \newcommand{\CC}[1][]{\protect\CCIcon{#1}\xspace} % C++ symbolic name 45 \newcommand{\Cpp}[1][]{\CC{#1}} % C++ synonym 45 46 % numbers disallowed in latex variables names => use number names 46 47 \newcommand{\CCeleven}{\protect\CCIcon{11}\xspace} % C++11 symbolic name … … 51 52 52 53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 55 \usepackage{pslatex} % reduce size of san serif font 56 \usepackage{relsize} % must be after change to small or selects old size 57 \usepackage{rotating} 58 \usepackage{calc} % latex arithmetic 53 59 54 60 % remove special-character warning in PDF side-bar names … … 72 78 \newlength{\parindentlnth} 73 79 \setlength{\parindentlnth}{\parindent} 74 75 \usepackage{pslatex} % reduce size of san serif font76 \usepackage{relsize} % must be after change to small or selects old size77 \usepackage{rotating}78 \usepackage{calc} % latex arithmetic79 80 80 81 % reduce size of chapter/section titles … … 152 153 \newcommand{\@snewterm}[2][\@empty]{{\newtermFontInline{#2}}\ifx#1\@empty\index{#2}\else\index{#1@{\protect#2}}\fi} 153 154 155 % \snake{<identifier>} 156 % Improves writing of snake case (or any convention that uses _) by allowing 157 % line breaks after _. Disables commands inside the block and formats the 158 % identifier to look like code. 159 \newcommand*\snake[1]{\snakefont{\expandafter\snake@next\detokenize{#1}\@nil}} 160 161 % \snakefont{<text>} 162 % Command used by \snake, you may renew the command to change its formating. 163 \newcommand*\snakefont[1]{\LstBasicStyle{#1}} 164 165 % Thanks Manuel of TeX Stack exchange. (I got the base pattern from one of 166 % their answers.) Note: \@nil should never be defined. 167 \newcommand*\snake@next[1]{\ifx\@nil#1\else 168 \expandafter\ifx\string_#1\string_\allowbreak\else#1\fi 169 \expandafter\snake@next\fi 170 } 171 172 % \lang{<language>}{<code>} 173 % Use the listings package to format the snipit of <code> in <language>. 174 \newcommand{\lang}[2]{\lstinline[language=#1]{#2}} 175 154 176 % Latin abbreviation 155 177 \newcommand{\abbrevFont}{\textit} % set empty for no italics … … 268 290 extendedchars=true, % allow ASCII characters in the range 128-255 269 291 escapechar=\$, % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-' 270 mathescape=false, % LaTeX math escape in CFA code $...$292 mathescape=false, % disable LaTeX math escape in CFA code $...$ 271 293 keepspaces=true, % 272 294 showstringspaces=false, % do not show spaces with cup -
doc/theses/thierry_delisle_PhD/thesis/Makefile
r21a99cc ra554e5f4 48 48 ## Define the documents that need to be made. 49 49 all: thesis.pdf 50 thesis.pdf: ${TEXTS} ${FIGURES} ${PICTURES} thesis.tex glossary.tex local.bib 50 thesis.pdf: ${TEXTS} ${FIGURES} ${PICTURES} thesis.tex glossary.tex local.bib ../../../LaTeXmacros/common.tex ../../../LaTeXmacros/common.sty 51 51 52 52 DOCUMENT = thesis.pdf -
libcfa/src/concurrency/preemption.cfa
r21a99cc ra554e5f4 251 251 bool enabled = __cfaabi_tls.preemption_state.enabled; 252 252 253 // Check if there is a pending preemption 254 processor * proc = __cfaabi_tls.this_processor; 255 bool pending = proc ? proc->pending_preemption : false; 256 if( enabled && pending ) proc->pending_preemption = false; 257 253 258 // create a assembler label after 254 259 // marked as clobber all to avoid movement 255 260 __cfaasm_label(check, after); 261 262 // If we can preempt and there is a pending one 263 // this is a good time to yield 264 if( enabled && pending ) { 265 force_yield( __POLL_PREEMPTION ); 266 } 256 267 return enabled; 257 268 } … … 282 293 // marked as clobber all to avoid movement 283 294 __cfaasm_label(get, after); 295 296 // This is used everywhere, to avoid cost, we DO NOT poll pending preemption 284 297 return val; 285 298 } … … 358 371 if(!ready) { abort("Preemption should be ready"); } 359 372 360 __cfaasm_label(debug, before); 361 362 sigset_t oldset; 363 int ret; 364 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary 365 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); } 366 367 ret = sigismember(&oldset, SIGUSR1); 368 if(ret < 0) { abort("ERROR sigismember returned %d", ret); } 369 if(ret == 1) { abort("ERROR SIGUSR1 is disabled"); } 370 371 ret = sigismember(&oldset, SIGALRM); 372 if(ret < 0) { abort("ERROR sigismember returned %d", ret); } 373 if(ret == 0) { abort("ERROR SIGALRM is enabled"); } 374 375 ret = sigismember(&oldset, SIGTERM); 376 if(ret < 0) { abort("ERROR sigismember returned %d", ret); } 377 if(ret == 1) { abort("ERROR SIGTERM is disabled"); } 378 379 __cfaasm_label(debug, after); 373 sigset_t oldset; 374 int ret; 375 ret = pthread_sigmask(0, ( const sigset_t * ) 0p, &oldset); // workaround trac#208: cast should be unnecessary 376 if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); } 377 378 ret = sigismember(&oldset, SIGUSR1); 379 if(ret < 0) { abort("ERROR sigismember returned %d", ret); } 380 if(ret == 1) { abort("ERROR SIGUSR1 is disabled"); } 381 382 ret = sigismember(&oldset, SIGALRM); 383 if(ret < 0) { abort("ERROR sigismember returned %d", ret); } 384 if(ret == 0) { abort("ERROR SIGALRM is enabled"); } 385 386 ret = sigismember(&oldset, SIGTERM); 387 if(ret < 0) { abort("ERROR sigismember returned %d", ret); } 388 if(ret == 1) { abort("ERROR SIGTERM is disabled"); } 380 389 } 381 390 … … 548 557 __cfaasm_label( check ); 549 558 __cfaasm_label( dsable ); 550 __cfaasm_label( debug );559 // __cfaasm_label( debug ); 551 560 552 561 // Check if preemption is safe … … 555 564 if( __cfaasm_in( ip, check ) ) { ready = false; goto EXIT; }; 556 565 if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; }; 557 if( __cfaasm_in( ip, debug ) ) { ready = false; goto EXIT; };566 // if( __cfaasm_in( ip, debug ) ) { ready = false; goto EXIT; }; 558 567 if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; }; 559 568 if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; }; … … 661 670 662 671 // Check if it is safe to preempt here 663 if( !preemption_ready( ip ) ) { return; } 672 if( !preemption_ready( ip ) ) { 673 #if !defined(__CFA_NO_STATISTICS__) 674 __cfaabi_tls.this_stats->ready.threads.preempt.rllfwd++; 675 #endif 676 return; 677 } 664 678 665 679 __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p @ %p).\n", __cfaabi_tls.this_processor, __cfaabi_tls.this_thread, (void *)(cxt->uc_mcontext.CFA_REG_IP) ); … … 680 694 681 695 // Preemption can occur here 696 697 #if !defined(__CFA_NO_STATISTICS__) 698 __cfaabi_tls.this_stats->ready.threads.preempt.yield++; 699 #endif 682 700 683 701 force_yield( __ALARM_PREEMPTION ); // Do the actual __cfactx_switch -
libcfa/src/concurrency/stats.cfa
r21a99cc ra554e5f4 29 29 stats->ready.threads.threads = 0; 30 30 stats->ready.threads.cthreads = 0; 31 stats->ready.threads.preempt.yield = 0; 32 stats->ready.threads.preempt.rllfwd = 0; 31 33 stats->ready.sleep.halts = 0; 32 34 stats->ready.sleep.cancels = 0; … … 77 79 78 80 void __tally_stats( struct __stats_t * cltr, struct __stats_t * proc ) { 79 tally_one( &cltr->ready.push.local.attempt, &proc->ready.push.local.attempt ); 80 tally_one( &cltr->ready.push.local.success, &proc->ready.push.local.success ); 81 tally_one( &cltr->ready.push.share.attempt, &proc->ready.push.share.attempt ); 82 tally_one( &cltr->ready.push.share.success, &proc->ready.push.share.success ); 83 tally_one( &cltr->ready.push.extrn.attempt, &proc->ready.push.extrn.attempt ); 84 tally_one( &cltr->ready.push.extrn.success, &proc->ready.push.extrn.success ); 85 tally_one( &cltr->ready.pop.local .attempt, &proc->ready.pop.local .attempt ); 86 tally_one( &cltr->ready.pop.local .success, &proc->ready.pop.local .success ); 87 tally_one( &cltr->ready.pop.help .attempt, &proc->ready.pop.help .attempt ); 88 tally_one( &cltr->ready.pop.help .success, &proc->ready.pop.help .success ); 89 tally_one( &cltr->ready.pop.steal .attempt, &proc->ready.pop.steal .attempt ); 90 tally_one( &cltr->ready.pop.steal .success, &proc->ready.pop.steal .success ); 91 tally_one( &cltr->ready.pop.search.attempt, &proc->ready.pop.search.attempt ); 92 tally_one( &cltr->ready.pop.search.success, &proc->ready.pop.search.success ); 93 tally_one( &cltr->ready.threads.migration , &proc->ready.threads.migration ); 94 tally_one( &cltr->ready.threads.extunpark , &proc->ready.threads.extunpark ); 95 tally_one( &cltr->ready.threads.threads , &proc->ready.threads.threads ); 96 tally_one( &cltr->ready.threads.cthreads , &proc->ready.threads.cthreads ); 97 tally_one( &cltr->ready.sleep.halts , &proc->ready.sleep.halts ); 98 tally_one( &cltr->ready.sleep.cancels , &proc->ready.sleep.cancels ); 99 tally_one( &cltr->ready.sleep.early , &proc->ready.sleep.early ); 100 tally_one( &cltr->ready.sleep.wakes , &proc->ready.sleep.wakes ); 101 tally_one( &cltr->ready.sleep.seen , &proc->ready.sleep.wakes ); 102 tally_one( &cltr->ready.sleep.exits , &proc->ready.sleep.exits ); 81 tally_one( &cltr->ready.push.local.attempt , &proc->ready.push.local.attempt ); 82 tally_one( &cltr->ready.push.local.success , &proc->ready.push.local.success ); 83 tally_one( &cltr->ready.push.share.attempt , &proc->ready.push.share.attempt ); 84 tally_one( &cltr->ready.push.share.success , &proc->ready.push.share.success ); 85 tally_one( &cltr->ready.push.extrn.attempt , &proc->ready.push.extrn.attempt ); 86 tally_one( &cltr->ready.push.extrn.success , &proc->ready.push.extrn.success ); 87 tally_one( &cltr->ready.pop.local .attempt , &proc->ready.pop.local .attempt ); 88 tally_one( &cltr->ready.pop.local .success , &proc->ready.pop.local .success ); 89 tally_one( &cltr->ready.pop.help .attempt , &proc->ready.pop.help .attempt ); 90 tally_one( &cltr->ready.pop.help .success , &proc->ready.pop.help .success ); 91 tally_one( &cltr->ready.pop.steal .attempt , &proc->ready.pop.steal .attempt ); 92 tally_one( &cltr->ready.pop.steal .success , &proc->ready.pop.steal .success ); 93 tally_one( &cltr->ready.pop.search.attempt , &proc->ready.pop.search.attempt ); 94 tally_one( &cltr->ready.pop.search.success , &proc->ready.pop.search.success ); 95 tally_one( &cltr->ready.threads.migration , &proc->ready.threads.migration ); 96 tally_one( &cltr->ready.threads.extunpark , &proc->ready.threads.extunpark ); 97 tally_one( &cltr->ready.threads.threads , &proc->ready.threads.threads ); 98 tally_one( &cltr->ready.threads.cthreads , &proc->ready.threads.cthreads ); 99 tally_one( &cltr->ready.threads.preempt.yield , &proc->ready.threads.preempt.yield ); 100 tally_one( &cltr->ready.threads.preempt.rllfwd, &proc->ready.threads.preempt.rllfwd ); 101 tally_one( &cltr->ready.sleep.halts , &proc->ready.sleep.halts ); 102 tally_one( &cltr->ready.sleep.cancels , &proc->ready.sleep.cancels ); 103 tally_one( &cltr->ready.sleep.early , &proc->ready.sleep.early ); 104 tally_one( &cltr->ready.sleep.wakes , &proc->ready.sleep.wakes ); 105 tally_one( &cltr->ready.sleep.seen , &proc->ready.sleep.wakes ); 106 tally_one( &cltr->ready.sleep.exits , &proc->ready.sleep.exits ); 103 107 104 108 #if defined(CFA_HAVE_LINUX_IO_URING_H) … … 168 172 | eng3(ready.sleep.wakes + ready.sleep.early) | '(' | eng3(ready.sleep.early) | ',' | eng3(ready.sleep.seen) | ')' | " wake(early, seen)," 169 173 | eng3(ready.sleep.exits) | "exit"; 174 sstr | "- Preemption : " | eng3(ready.threads.preempt.yield) | "yields," | eng3(ready.threads.preempt.rllfwd) | "delayed"; 170 175 sstr | nl; 171 176 } -
libcfa/src/concurrency/stats.hfa
r21a99cc ra554e5f4 65 65 volatile int64_t threads; // number of threads in the system, includes only local change 66 66 volatile int64_t cthreads; // number of threads in the system, includes only local change 67 struct { 68 volatile uint64_t yield; 69 volatile uint64_t rllfwd; 70 } preempt; 67 71 } threads; 68 72 struct { -
libcfa/src/stdhdr/pthread.h
r21a99cc ra554e5f4 10 10 // Created On : Wed Jun 16 13:39:06 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jun 16 13:39:42 202113 // Update Count : 1 12 // Last Modified On : Thu Feb 3 21:53:26 2022 13 // Update Count : 13 14 14 // 15 15 16 // pthread.h and setjmp.h cannot agree on the type of __sigsetjmp: 17 // 18 // extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__)); 19 // extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __attribute__ ((__nothrow__)); 20 // 21 // With -Wall, gcc-11 warns about the disagreement unless the CPP directive 22 // 23 // # 1 "/usr/include/pthread.h" 1 3 4 24 // 25 // appears, which appears to be witchcraft. Unfortunately, this directive is removed by the CFA preprocessor, so the 26 // batchtest fails because of the spurious warning message. Hence, the warning is elided. 27 16 28 extern "C" { 29 #if defined(__GNUC__) && __GNUC__ == 11 30 #pragma GCC diagnostic push 31 #pragma GCC diagnostic ignored "-Warray-parameter" 32 #endif // defined(__GNUC__) && __GNUC__ == 11 33 17 34 #include_next <pthread.h> // has internal check for multiple expansion 35 36 #if defined(__GNUC__) && __GNUC__ == 11 37 #pragma GCC diagnostic pop 38 #endif // defined(__GNUC__) && __GNUC__ == 11 18 39 } // extern "C" 19 40 20 41 // Local Variables: // 21 // tab-width: 4 //22 42 // mode: c++ // 23 // compile-command: "make install" //24 43 // End: // -
libcfa/src/stdhdr/setjmp.h
r21a99cc ra554e5f4 10 10 // Created On : Mon Jul 4 23:25:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T ue Jul 5 20:38:33 201613 // Update Count : 1 212 // Last Modified On : Thu Feb 3 21:53:28 2022 13 // Update Count : 18 14 14 // 15 15 16 // pthread.h and setjmp.h cannot agree on the type of __sigsetjmp: 17 // 18 // extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __attribute__ ((__nothrow__)); 19 // extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __attribute__ ((__nothrow__)); 20 // 21 // With -Wall, gcc-11 warns about the disagreement unless the CPP directive 22 // 23 // # 1 "/usr/include/pthread.h" 1 3 4 24 // 25 // appears, which appears to be witchcraft. Unfortunately, this directive is removed by the CFA preprocessor, so the 26 // batchtest fails because of the spurious warning message. Hence, the warning is elided. 27 16 28 extern "C" { 29 #if defined(__GNUC__) && __GNUC__ == 11 30 #pragma GCC diagnostic push 31 #pragma GCC diagnostic ignored "-Warray-parameter" 32 #endif // defined(__GNUC__) && __GNUC__ == 11 33 17 34 #include_next <setjmp.h> // has internal check for multiple expansion 35 36 #if defined(__GNUC__) && __GNUC__ == 11 37 #pragma GCC diagnostic pop 38 #endif // defined(__GNUC__) && __GNUC__ == 11 18 39 } // extern "C" 19 40 20 41 // Local Variables: // 21 // tab-width: 4 //22 42 // mode: c++ // 23 // compile-command: "make install" //24 43 // End: // -
src/AST/Pass.hpp
r21a99cc ra554e5f4 238 238 239 239 private: 240 const ast::Stmt * call_accept( const ast::Stmt * ); 241 const ast::Expr * call_accept( const ast::Expr * ); 242 243 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. 244 245 const ast::Stmt * call_accept_as_compound(const ast::Stmt *); 246 240 241 // Regular nodes 247 242 template< typename node_t > 248 auto call_accept( const node_t * node ) -> typename std::enable_if< 243 struct result1 { 244 bool differs; 245 const node_t * value; 246 247 template< typename object_t, typename super_t, typename field_t > 248 void apply(object_t *, field_t super_t::* field); 249 }; 250 251 result1<ast::Stmt> call_accept( const ast::Stmt * ); 252 result1<ast::Expr> call_accept( const ast::Expr * ); 253 254 template< typename node_t > 255 auto call_accept( const node_t * node ) 256 -> typename std::enable_if< 249 257 !std::is_base_of<ast::Expr, node_t>::value && 250 258 !std::is_base_of<ast::Stmt, node_t>::value 251 , decltype( node->accept(*this) ) 259 , result1< 260 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 261 > 252 262 >::type; 253 263 264 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. 265 result1<ast::Stmt> call_accept_as_compound(const ast::Stmt *); 266 267 // Container of statements 254 268 template< template <class...> class container_t > 255 container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & ); 256 269 struct resultNstmt { 270 struct delta { 271 ptr<Stmt> nval; 272 ssize_t old_idx; 273 bool is_old; 274 275 delta(const Stmt * s, ssize_t i, bool old) : nval{s}, old_idx{i}, is_old{old} {} 276 }; 277 278 bool differs; 279 container_t< delta > values; 280 281 resultNstmt() : differs(false), values{} {} 282 resultNstmt(bool diff, container_t< delta > && vals) : differs(diff), values(vals) {} 283 284 template< typename object_t, typename super_t, typename field_t > 285 void apply(object_t *, field_t super_t::* field); 286 287 template< template <class...> class incontainer_t > 288 void take_all( incontainer_t<ast::ptr<ast::Stmt>> * stmts ) { 289 if(!stmts || stmts->empty()) return; 290 291 std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ), [](ast::ptr<ast::Stmt>& decl) -> delta { 292 return delta( decl.release(), -1, false ); 293 }); 294 stmts->clear(); 295 differs = true; 296 } 297 298 template< template <class...> class incontainer_t > 299 void take_all( incontainer_t<ast::ptr<ast::Decl>> * decls ) { 300 if(!decls || decls->empty()) return; 301 302 std::transform(decls->begin(), decls->end(), std::back_inserter( values ), [](ast::ptr<ast::Decl>& decl) -> auto { 303 auto loc = decl->location; 304 auto stmt = new DeclStmt( loc, decl.release() ); 305 return delta( stmt, -1, false ); 306 }); 307 decls->clear(); 308 differs = true; 309 } 310 }; 311 312 template< template <class...> class container_t > 313 resultNstmt<container_t> call_accept( const container_t< ptr<Stmt> > & ); 314 315 // Container of something 257 316 template< template <class...> class container_t, typename node_t > 258 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 317 struct resultN { 318 bool differs; 319 container_t<ptr<node_t>> values; 320 321 template< typename object_t, typename super_t, typename field_t > 322 void apply(object_t *, field_t super_t::* field); 323 }; 324 325 template< template <class...> class container_t, typename node_t > 326 resultN< container_t, node_t > call_accept( const container_t< ptr<node_t> > & container ); 259 327 260 328 public: 261 329 /// Logic to call the accept and mutate the parent if needed, delegates call to accept 262 template<typename node_t, typename parent_t, typename child_t>263 void maybe_accept(const node_t * &, child_t parent_t::* child);264 265 template<typename node_t, typename parent_t, typename child_t>266 void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);330 template<typename node_t, typename parent_t, typename field_t> 331 void maybe_accept(const node_t * &, field_t parent_t::* field); 332 333 template<typename node_t, typename parent_t, typename field_t> 334 void maybe_accept_as_compound(const node_t * &, field_t parent_t::* field); 267 335 268 336 private: -
src/AST/Pass.impl.hpp
r21a99cc ra554e5f4 79 79 80 80 template<typename it_t, template <class...> class container_t> 81 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * decls, bool * mutated = nullptr ) {82 if(empty( decls)) return;83 84 std::move( decls->begin(), decls->end(), it);85 decls->clear();81 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) { 82 if(empty(stmts)) return; 83 84 std::move(stmts->begin(), stmts->end(), it); 85 stmts->clear(); 86 86 if(mutated) *mutated = true; 87 87 } … … 123 123 return !new_val.empty(); 124 124 } 125 } 126 127 128 template< typename core_t > 129 template< typename node_t > 130 template< typename object_t, typename super_t, typename field_t > 131 void ast::Pass< core_t >::result1< node_t >::apply(object_t * object, field_t super_t::* field) { 132 object->*field = value; 125 133 } 126 134 … … 131 139 !std::is_base_of<ast::Expr, node_t>::value && 132 140 !std::is_base_of<ast::Stmt, node_t>::value 133 , decltype( node->accept(*this) ) 141 , ast::Pass< core_t >::result1< 142 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 143 > 134 144 >::type 135 145 { … … 140 150 static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR"); 141 151 142 return node->accept( *this ); 152 auto nval = node->accept( *this ); 153 ast::Pass< core_t >::result1< 154 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 155 > res; 156 res.differs = nval != node; 157 res.value = nval; 158 return res; 143 159 } 144 160 145 161 template< typename core_t > 146 const ast::Expr *ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {162 typename ast::Pass< core_t >::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 147 163 __pedantic_pass_assert( __visit_children() ); 148 164 __pedantic_pass_assert( expr ); … … 153 169 } 154 170 155 return expr->accept( *this ); 171 auto nval = expr->accept( *this ); 172 return { nval != expr, nval }; 156 173 } 157 174 158 175 template< typename core_t > 159 const ast::Stmt *ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {176 typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 160 177 __pedantic_pass_assert( __visit_children() ); 161 178 __pedantic_pass_assert( stmt ); 162 179 163 return stmt->accept( *this ); 180 const ast::Stmt * nval = stmt->accept( *this ); 181 return { nval != stmt, nval }; 164 182 } 165 183 166 184 template< typename core_t > 167 const ast::Stmt *ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {185 typename ast::Pass< core_t >::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) { 168 186 __pedantic_pass_assert( __visit_children() ); 169 187 __pedantic_pass_assert( stmt ); … … 190 208 // If the pass doesn't want to add anything then we are done 191 209 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) { 192 return nstmt;210 return { nstmt != stmt, nstmt }; 193 211 } 194 212 … … 212 230 __pass::take_all( std::back_inserter( compound->kids ), stmts_after ); 213 231 214 return compound;232 return {true, compound}; 215 233 } 216 234 217 235 template< typename core_t > 218 236 template< template <class...> class container_t > 219 container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 237 template< typename object_t, typename super_t, typename field_t > 238 void ast::Pass< core_t >::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) { 239 auto & container = object->*field; 240 __pedantic_pass_assert( container.size() <= values.size() ); 241 242 auto cit = enumerate(container).begin(); 243 244 container_t<ptr<Stmt>> nvals; 245 for(delta & d : values) { 246 if( d.is_old ) { 247 __pedantic_pass_assert( cit.idx <= d.old_idx ); 248 std::advance( cit, d.old_idx - cit.idx ); 249 nvals.push_back( std::move( (*cit).val) ); 250 } else { 251 nvals.push_back( std::move(d.nval) ); 252 } 253 } 254 255 object->*field = std::move(nvals); 256 } 257 258 template< typename core_t > 259 template< template <class...> class container_t > 260 typename ast::Pass< core_t >::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 220 261 __pedantic_pass_assert( __visit_children() ); 221 262 if( statements.empty() ) return {}; … … 244 285 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 245 286 246 bool mutated = false; 247 container_t< ptr<Stmt> > new_kids; 248 for( const Stmt * stmt : statements ) { 287 resultNstmt<container_t> new_kids; 288 for( auto value : enumerate( statements ) ) { 249 289 try { 290 size_t i = value.idx; 291 const Stmt * stmt = value.val; 250 292 __pedantic_pass_assert( stmt ); 251 293 const ast::Stmt * new_stmt = stmt->accept( *this ); 252 294 assert( new_stmt ); 253 if(new_stmt != stmt ) mutated = true;295 if(new_stmt != stmt ) { new_kids.differs = true; } 254 296 255 297 // Make sure that it is either adding statements or declartions but not both … … 261 303 262 304 // Take all the statements which should have gone after, N/A for first iteration 263 __pass::take_all( std::back_inserter( new_kids ), decls_before, &mutated);264 __pass::take_all( std::back_inserter( new_kids ), stmts_before, &mutated);305 new_kids.take_all( decls_before ); 306 new_kids.take_all( stmts_before ); 265 307 266 308 // Now add the statement if there is one 267 new_kids.emplace_back( new_stmt ); 309 if(new_stmt != stmt) { 310 new_kids.values.emplace_back( new_stmt, i, false ); 311 } else { 312 new_kids.values.emplace_back( nullptr, i, true ); 313 } 268 314 269 315 // Take all the declarations that go before 270 __pass::take_all( std::back_inserter( new_kids ), decls_after, &mutated);271 __pass::take_all( std::back_inserter( new_kids ), stmts_after, &mutated);316 new_kids.take_all( decls_after ); 317 new_kids.take_all( stmts_after ); 272 318 } 273 319 catch ( SemanticErrorException &e ) { … … 278 324 if ( !errors.isEmpty() ) { throw errors; } 279 325 280 return mutated ? new_kids : container_t< ptr<Stmt> >();326 return new_kids; 281 327 } 282 328 283 329 template< typename core_t > 284 330 template< template <class...> class container_t, typename node_t > 285 container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 331 template< typename object_t, typename super_t, typename field_t > 332 void ast::Pass< core_t >::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) { 333 auto & container = object->*field; 334 __pedantic_pass_assert( container.size() == values.size() ); 335 336 for(size_t i = 0; i < container.size(); i++) { 337 // Take all the elements that are different in 'values' 338 // and swap them into 'container' 339 if( values[i] != nullptr ) std::swap(container[i], values[i]); 340 } 341 342 // Now the original containers should still have the unchanged values 343 // but also contain the new values 344 } 345 346 template< typename core_t > 347 template< template <class...> class container_t, typename node_t > 348 typename ast::Pass< core_t >::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 286 349 __pedantic_pass_assert( __visit_children() ); 287 350 if( container.empty() ) return {}; … … 293 356 294 357 bool mutated = false; 295 container_t< ast::ptr<node_t>> new_kids;358 container_t<ptr<node_t>> new_kids; 296 359 for ( const node_t * node : container ) { 297 360 try { 298 361 __pedantic_pass_assert( node ); 299 362 const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) ); 300 if(new_stmt != node ) mutated = true; 301 302 new_kids.emplace_back( new_stmt ); 363 if(new_stmt != node ) { 364 mutated = true; 365 new_kids.emplace_back( new_stmt ); 366 } else { 367 new_kids.emplace_back( nullptr ); 368 } 369 303 370 } 304 371 catch( SemanticErrorException &e ) { … … 306 373 } 307 374 } 375 376 __pedantic_pass_assert( new_kids.size() == container.size() ); 308 377 pass_visitor_stats.depth--; 309 378 if ( ! errors.isEmpty() ) { throw errors; } 310 379 311 return mutated ? new_kids : container_t< ast::ptr<node_t> >();380 return ast::Pass< core_t >::resultN<container_t, node_t>{ mutated, new_kids }; 312 381 } 313 382 … … 327 396 auto new_val = call_accept( old_val ); 328 397 329 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");330 331 if( __pass::differs(old_val, new_val)) {398 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR"); 399 400 if( new_val.differs ) { 332 401 auto new_parent = __pass::mutate<core_t>(parent); 333 new_ parent->*child = new_val;402 new_val.apply(new_parent, child); 334 403 parent = new_parent; 335 404 } … … 353 422 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR"); 354 423 355 if( __pass::differs(old_val, new_val)) {424 if( new_val.differs ) { 356 425 auto new_parent = __pass::mutate<core_t>(parent); 357 new_ parent->*child = new_val;426 new_val.apply( new_parent, child ); 358 427 parent = new_parent; 359 428 } … … 941 1010 const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr; 942 1011 if(func != clause.target.func) mutated = true; 1012 else func = nullptr; 943 1013 944 1014 std::vector<ptr<Expr>> new_args; … … 946 1016 for( const auto & arg : clause.target.args ) { 947 1017 auto a = arg->accept(*this); 948 new_args.push_back( a ); 949 if( a != arg ) mutated = true; 1018 if( a != arg ) { 1019 mutated = true; 1020 new_args.push_back( a ); 1021 } else 1022 new_args.push_back( nullptr ); 950 1023 } 951 1024 952 1025 const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr; 953 1026 if(stmt != clause.stmt) mutated = true; 1027 else stmt = nullptr; 954 1028 955 1029 const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr; 956 1030 if(cond != clause.cond) mutated = true; 1031 else cond = nullptr; 957 1032 958 1033 new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } ); … … 961 1036 if(mutated) { 962 1037 auto n = __pass::mutate<core_t>(node); 963 n->clauses = std::move( new_clauses ); 1038 for(size_t i = 0; i < new_clauses.size(); i++) { 1039 if(new_clauses.at(i).target.func != nullptr) std::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func); 1040 1041 for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) { 1042 if(new_clauses.at(i).target.args.at(j) != nullptr) std::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j)); 1043 } 1044 1045 if(new_clauses.at(i).stmt != nullptr) std::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt); 1046 if(new_clauses.at(i).cond != nullptr) std::swap(n->clauses.at(i).cond, new_clauses.at(i).cond); 1047 } 964 1048 node = n; 965 1049 } … … 969 1053 if(node->field) { \ 970 1054 auto nval = call_accept( node->field ); \ 971 if(nval != node->field) { \1055 if(nval.differs ) { \ 972 1056 auto nparent = __pass::mutate<core_t>(node); \ 973 nparent->field = nval ; \1057 nparent->field = nval.value; \ 974 1058 node = nparent; \ 975 1059 } \ -
src/AST/Stmt.cpp
r21a99cc ra554e5f4 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed May 8 13:00:00 2019 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed May 15 15:53:00 201913 // Update Count : 211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 2 19:01:20 2022 13 // Update Count : 3 14 14 // 15 15 … … 56 56 57 57 // --- BranchStmt 58 BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )59 : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {58 BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, const std::vector<Label>&& labels ) 59 : Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) { 60 60 // Make sure a syntax error hasn't slipped through. 61 61 assert( Goto != kind || !target.empty() ); -
src/AST/Stmt.hpp
r21a99cc ra554e5f4 10 10 // Created On : Wed May 8 13:00:00 2019 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 1 17:44:46202213 // Update Count : 2412 // Last Modified On : Wed Feb 2 20:06:41 2022 13 // Update Count : 34 14 14 // 15 15 … … 39 39 std::vector<Label> labels; 40 40 41 Stmt( const CodeLocation & loc, std::vector<Label> && labels = {} )41 Stmt( const CodeLocation & loc, const std::vector<Label> && labels = {} ) 42 42 : ParseNode(loc), labels(std::move(labels)) {} 43 43 … … 55 55 std::list<ptr<Stmt>> kids; 56 56 57 CompoundStmt(const CodeLocation & loc, std::list<ptr<Stmt>> && ks = {}, 58 std::vector<Label> && labels = {} ) 57 CompoundStmt(const CodeLocation & loc, const std::list<ptr<Stmt>> && ks = {}, const std::vector<Label> && labels = {} ) 59 58 : Stmt(loc, std::move(labels)), kids(std::move(ks)) {} 60 59 … … 74 73 class NullStmt final : public Stmt { 75 74 public: 76 NullStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )75 NullStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} ) 77 76 : Stmt(loc, std::move(labels)) {} 78 77 … … 88 87 ptr<Expr> expr; 89 88 90 ExprStmt( const CodeLocation & loc, const Expr* e, std::vector<Label> && labels = {} )89 ExprStmt( const CodeLocation & loc, const Expr* e, const std::vector<Label> && labels = {} ) 91 90 : Stmt(loc, std::move(labels)), expr(e) {} 92 91 … … 107 106 108 107 AsmStmt( const CodeLocation & loc, bool isVolatile, const Expr * instruction, 109 std::vector<ptr<Expr>> && output,std::vector<ptr<Expr>> && input,110 std::vector<ptr<ConstantExpr>> && clobber,std::vector<Label> && gotoLabels,111 std::vector<Label> && labels = {})108 const std::vector<ptr<Expr>> && output, const std::vector<ptr<Expr>> && input, 109 const std::vector<ptr<ConstantExpr>> && clobber, const std::vector<Label> && gotoLabels, 110 const std::vector<Label> && labels = {}) 112 111 : Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction), 113 112 output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)), … … 144 143 145 144 IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * then, 146 const Stmt * else_ = nullptr, std::vector<ptr<Stmt>> && inits = {},147 std::vector<Label> && labels = {} )145 const Stmt * else_ = nullptr, const std::vector<ptr<Stmt>> && inits = {}, 146 const std::vector<Label> && labels = {} ) 148 147 : Stmt(loc, std::move(labels)), cond(cond), then(then), else_(else_), 149 148 inits(std::move(inits)) {} … … 161 160 std::vector<ptr<Stmt>> stmts; 162 161 163 SwitchStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,164 std::vector<Label> && labels = {} )162 SwitchStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts, 163 const std::vector<Label> && labels = {} ) 165 164 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {} 166 165 … … 178 177 std::vector<ptr<Stmt>> stmts; 179 178 180 CaseStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,181 std::vector<Label> && labels = {} )179 CaseStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts, 180 const std::vector<Label> && labels = {} ) 182 181 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {} 183 182 … … 200 199 201 200 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, 202 std::vector<ptr<Stmt>> && inits, bool isDoWhile = false,std::vector<Label> && labels = {} )201 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} ) 203 202 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {} 204 203 205 204 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_, 206 std::vector<ptr<Stmt>> && inits, bool isDoWhile = false,std::vector<Label> && labels = {} )205 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} ) 207 206 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {} 208 207 … … 222 221 ptr<Stmt> else_; 223 222 224 ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,225 const Expr * inc, const Stmt * body, std::vector<Label> && label = {} )223 ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond, 224 const Expr * inc, const Stmt * body, const std::vector<Label> && label = {} ) 226 225 : Stmt(loc, std::move(label)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(nullptr) {} 227 226 228 ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,229 const Expr * inc, const Stmt * body, const Stmt * else_, std::vector<Label> && labels = {} )227 ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond, 228 const Expr * inc, const Stmt * body, const Stmt * else_, const std::vector<Label> && labels = {} ) 230 229 : Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(else_) {} 231 230 … … 247 246 Kind kind; 248 247 249 BranchStmt( const CodeLocation & loc, Kind kind, Label target, 250 std::vector<Label> && labels = {} ); 251 BranchStmt( const CodeLocation & loc, const Expr * computedTarget, 252 std::vector<Label> && labels = {} ) 253 : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc), 254 computedTarget(computedTarget), kind(Goto) {} 248 BranchStmt( const CodeLocation & loc, Kind kind, Label target, const std::vector<Label> && labels = {} ); 249 BranchStmt( const CodeLocation & loc, const Expr * computedTarget, const std::vector<Label> && labels = {} ) 250 : Stmt(loc, std::move(labels)), originalTarget(loc), target(loc), computedTarget(computedTarget), kind(Goto) {} 255 251 256 252 const char * kindName() const { return kindNames[kind]; } … … 269 265 ptr<Expr> expr; 270 266 271 ReturnStmt( const CodeLocation & loc, const Expr * expr, std::vector<Label> && labels = {} )267 ReturnStmt( const CodeLocation & loc, const Expr * expr, const std::vector<Label> && labels = {} ) 272 268 : Stmt(loc, std::move(labels)), expr(expr) {} 273 269 … … 288 284 ExceptionKind kind; 289 285 290 ThrowStmt( 291 const CodeLocation & loc, ExceptionKind kind, const Expr * expr, const Expr * target, 292 std::vector<Label> && labels = {} ) 286 ThrowStmt( const CodeLocation & loc, ExceptionKind kind, const Expr * expr, 287 const Expr * target, const std::vector<Label> && labels = {} ) 293 288 : Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {} 294 289 … … 306 301 ptr<FinallyStmt> finally; 307 302 308 TryStmt( 309 const CodeLocation & loc, const CompoundStmt * body, 310 std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally, 311 std::vector<Label> && labels = {} ) 303 TryStmt( const CodeLocation & loc, const CompoundStmt * body, 304 const std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally, 305 const std::vector<Label> && labels = {} ) 312 306 : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {} 313 307 … … 326 320 ExceptionKind kind; 327 321 328 CatchStmt( 329 const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond, 330 const Stmt * body, std::vector<Label> && labels = {} ) 322 CatchStmt( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond, 323 const Stmt * body, const std::vector<Label> && labels = {} ) 331 324 : Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {} 332 325 … … 358 351 enum Type { None, Coroutine, Generator } type = None; 359 352 360 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, std::vector<Label> && labels = {} )353 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} ) 361 354 : Stmt(loc, std::move(labels)), then(then), type(type) {} 362 355 … … 396 389 OrElse orElse; 397 390 398 WaitForStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )391 WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} ) 399 392 : Stmt(loc, std::move(labels)) {} 400 393 … … 410 403 ptr<Decl> decl; 411 404 412 DeclStmt( const CodeLocation & loc, const Decl * decl, std::vector<Label> && labels = {} )405 DeclStmt( const CodeLocation & loc, const Decl * decl, const std::vector<Label> && labels = {} ) 413 406 : Stmt(loc, std::move(labels)), decl(decl) {} 414 407 … … 441 434 442 435 MutexStmt( const CodeLocation & loc, const Stmt * stmt, 443 std::vector<ptr<Expr>> && mutexes,std::vector<Label> && labels = {} )436 const std::vector<ptr<Expr>> && mutexes, const std::vector<Label> && labels = {} ) 444 437 : Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {} 445 438 -
src/CodeGen/CodeGenerator.cc
r21a99cc ra554e5f4 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 1 16:29:25202213 // Update Count : 54 012 // Last Modified On : Wed Feb 2 20:30:30 2022 13 // Update Count : 541 14 14 // 15 15 #include "CodeGenerator.h" … … 1020 1020 output << "fallthru"; 1021 1021 break; 1022 default: ; // prevent warning 1022 1023 } // switch 1023 1024 // print branch target for labelled break/continue/fallthru in debug mode -
src/Common/CodeLocation.h
r21a99cc ra554e5f4 26 26 CodeLocation() = default; 27 27 28 28 29 /// Create a new CodeLocation with the given values. 29 30 CodeLocation( const char* filename, int lineno ) … … 33 34 34 35 CodeLocation( const CodeLocation& rhs ) = default; 36 CodeLocation( CodeLocation&& rhs ) = default; 37 CodeLocation& operator=( const CodeLocation & ) = default; 38 CodeLocation& operator=( CodeLocation && ) = default; 35 39 36 40 bool isSet () const { -
src/Common/utility.h
r21a99cc ra554e5f4 371 371 } 372 372 373 template< typename T > 374 struct enumerate_t { 375 template<typename val_t> 376 struct value_t { 377 val_t & val; 378 size_t idx; 379 }; 380 381 template< typename iter_t, typename val_t > 382 struct iterator_t { 383 iter_t it; 384 size_t idx; 385 386 iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {} 387 388 value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; } 389 390 bool operator==(const iterator_t & o) const { return o.it == it; } 391 bool operator!=(const iterator_t & o) const { return o.it != it; } 392 393 iterator_t & operator++() { 394 it++; 395 idx++; 396 return *this; 397 } 398 399 using difference_type = typename std::iterator_traits< iter_t >::difference_type; 400 using value_type = value_t<val_t>; 401 using pointer = value_t<val_t> *; 402 using reference = value_t<val_t> &; 403 using iterator_category = std::forward_iterator_tag; 404 }; 405 406 T & ref; 407 408 using iterator = iterator_t< typename T::iterator, typename T::value_type >; 409 using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >; 410 411 iterator begin() { return iterator( ref.begin(), 0 ); } 412 iterator end() { return iterator( ref.end(), ref.size() ); } 413 414 const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); } 415 const_iterator end() const { return const_iterator( ref.cend(), ref.size() ); } 416 417 const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); } 418 const_iterator cend() const { return const_iterator( ref.cend(), ref.size() ); } 419 }; 420 421 template< typename T > 422 enumerate_t<T> enumerate( T & ref ) { 423 return enumerate_t< T >{ ref }; 424 } 425 426 template< typename T > 427 const enumerate_t< const T > enumerate( const T & ref ) { 428 return enumerate_t< const T >{ ref }; 429 } 430 373 431 template< typename OutType, typename Range, typename Functor > 374 432 OutType map_range( const Range& range, Functor&& functor ) { -
src/ControlStruct/ExceptTranslate.h
r21a99cc ra554e5f4 31 31 32 32 void translateTries( std::list< Declaration *> & translationUnit ); 33 void translateTries( ast::TranslationUnit & transUnit ); 33 34 /* Replaces all try blocks (and their many clauses) with function definitions and calls. 34 35 * This uses the exception built-ins to produce typed output and should take place after -
src/ControlStruct/ExceptTranslateNew.cpp
r21a99cc ra554e5f4 20 20 #include "AST/Stmt.hpp" 21 21 #include "AST/TranslationUnit.hpp" 22 #include "AST/DeclReplacer.hpp" 22 23 23 24 namespace ControlStruct { 25 26 namespace { 27 28 typedef std::list<ast::CatchStmt*> CatchList; 29 30 void split( CatchList& allHandlers, CatchList& terHandlers, 31 CatchList& resHandlers ) { 32 while ( !allHandlers.empty() ) { 33 ast::CatchStmt * stmt = allHandlers.front(); 34 allHandlers.pop_front(); 35 if (stmt->kind == ast::ExceptionKind::Terminate) { 36 terHandlers.push_back(stmt); 37 } else { 38 resHandlers.push_back(stmt); 39 } 40 } 41 } 42 43 void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) { 44 block->push_back(new ast::DeclStmt(block->location, item)); 45 } 24 46 25 47 class TranslateThrowsCore : public ast::WithGuards { … … 126 148 } 127 149 150 151 class TryMutatorCore { 152 // The built in types used in translation. 153 const ast::StructDecl * except_decl; 154 const ast::StructDecl * node_decl; 155 const ast::StructDecl * hook_decl; 156 157 // The many helper functions for code/syntree generation. 158 ast::CompoundStmt * take_try_block( ast::TryStmt * tryStmt ); 159 ast::FunctionDecl * create_try_wrapper( const ast::CompoundStmt * body ); 160 ast::FunctionDecl * create_terminate_catch( CatchList &handlers ); 161 ast::CompoundStmt * create_single_matcher( 162 const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler ); 163 ast::FunctionDecl * create_terminate_match( CatchList &handlers ); 164 ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper, 165 ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match ); 166 ast::FunctionDecl * create_resume_handler( CatchList &handlers ); 167 ast::CompoundStmt * create_resume_wrapper( 168 const ast::Stmt * wraps, const ast::FunctionDecl * resume_handler ); 169 ast::FunctionDecl * create_finally_wrapper( ast::TryStmt * tryStmt ); 170 ast::ObjectDecl * create_finally_hook( ast::FunctionDecl * finally_wrapper ); 171 ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt ); 172 173 // Types used in translation, make sure to use clone. 174 // void (*function)(); 175 ast::FunctionDecl * try_func_t; 176 // void (*function)(int, exception); 177 ast::FunctionDecl * catch_func_t; 178 // int (*function)(exception); 179 ast::FunctionDecl * match_func_t; 180 // bool (*function)(exception); 181 ast::FunctionDecl * handle_func_t; 182 // void (*function)(__attribute__((unused)) void *); 183 ast::FunctionDecl * finally_func_t; 184 185 ast::StructInstType * create_except_type() { 186 assert( except_decl ); 187 return new ast::StructInstType( except_decl ); 188 } 189 void init_func_types(); 190 191 public: 192 TryMutatorCore() : 193 except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ) 194 {} 195 196 void previsit( const ast::StructDecl *structDecl ); 197 ast::Stmt * postvisit( const ast::TryStmt *tryStmt ); 198 ast::Stmt * postvisit( const ast::ThrowStmt *throwStmt ); 199 }; 200 201 void TryMutatorCore::init_func_types() { 202 assert( except_decl ); 203 204 ast::ObjectDecl index_obj( 205 {}, 206 "__handler_index", 207 new ast::BasicType(ast::BasicType::SignedInt) 208 ); 209 ast::ObjectDecl exception_obj( 210 {}, 211 "__exception_inst", 212 new ast::PointerType( 213 new ast::StructInstType( except_decl ) 214 ), 215 NULL 216 ); 217 ast::ObjectDecl bool_obj( 218 {}, 219 "__ret_bool", 220 new ast::BasicType( ast::BasicType::Bool ), 221 nullptr, //init 222 ast::Storage::Classes{}, 223 ast::Linkage::Cforall, 224 nullptr, //width 225 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 226 ); 227 ast::ObjectDecl voidptr_obj( 228 {}, 229 "__hook", 230 new ast::PointerType( 231 new ast::VoidType() 232 ), 233 nullptr, //init 234 ast::Storage::Classes{}, 235 ast::Linkage::Cforall, 236 nullptr, //width 237 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 238 ); 239 240 ast::ObjectDecl unused_index_obj( 241 {}, 242 "__handler_index", 243 new ast::BasicType(ast::BasicType::SignedInt), 244 nullptr, 245 ast::Storage::Classes{}, 246 ast::Linkage::Cforall, 247 nullptr, //width 248 std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) } 249 ); 250 //unused_index_obj->attributes.push_back( new Attribute( "unused" ) ); 251 252 try_func_t = new ast::FunctionDecl( 253 {}, 254 "try", 255 {}, //forall 256 {}, //no param 257 {}, //no return 258 nullptr, 259 ast::Storage::Classes{}, 260 ast::Linkage::Cforall 261 ); 262 263 catch_func_t = new ast::FunctionDecl( 264 {}, 265 "catch", 266 {}, //forall 267 {ast::deepCopy(&index_obj), ast::deepCopy(&exception_obj)},//param 268 {}, //return void 269 nullptr, 270 ast::Storage::Classes{}, 271 ast::Linkage::Cforall 272 ); 273 274 match_func_t = new ast::FunctionDecl( 275 {}, 276 "match", 277 {}, //forall 278 {ast::deepCopy(&exception_obj)}, 279 {ast::deepCopy(&unused_index_obj)}, 280 nullptr, 281 ast::Storage::Classes{}, 282 ast::Linkage::Cforall 283 ); 284 285 handle_func_t = new ast::FunctionDecl( 286 {}, 287 "handle", 288 {}, //forall 289 {ast::deepCopy(&exception_obj)}, 290 {ast::deepCopy(&bool_obj)}, 291 nullptr, 292 ast::Storage::Classes{}, 293 ast::Linkage::Cforall 294 ); 295 296 finally_func_t = new ast::FunctionDecl( 297 {}, 298 "finally", 299 {}, //forall 300 {ast::deepCopy(&voidptr_obj)}, 301 {}, //return void 302 nullptr, 303 ast::Storage::Classes{}, 304 ast::Linkage::Cforall 305 ); 306 307 //catch_func_t.get_parameters().push_back( index_obj.clone() ); 308 //catch_func_t.get_parameters().push_back( exception_obj.clone() ); 309 //match_func_t.get_returnVals().push_back( unused_index_obj ); 310 //match_func_t.get_parameters().push_back( exception_obj.clone() ); 311 //handle_func_t.get_returnVals().push_back( bool_obj.clone() ); 312 //handle_func_t.get_parameters().push_back( exception_obj.clone() ); 313 //finally_func_t.get_parameters().push_back( voidptr_obj.clone() ); 314 } 315 316 // TryStmt Mutation Helpers 317 318 /* 319 ast::CompoundStmt * TryMutatorCore::take_try_block( ast::TryStmt *tryStmt ) { 320 ast::CompoundStmt * block = tryStmt->body; 321 tryStmt->body = nullptr; 322 return block; 323 } 324 */ 325 326 ast::FunctionDecl * TryMutatorCore::create_try_wrapper( 327 const ast::CompoundStmt *body ) { 328 329 ast::FunctionDecl * ret = ast::deepCopy(try_func_t); 330 ret->stmts = body; 331 return ret; 332 } 333 334 ast::FunctionDecl * TryMutatorCore::create_terminate_catch( 335 CatchList &handlers ) { 336 std::vector<ast::ptr<ast::Stmt>> handler_wrappers; 337 338 assert (!handlers.empty()); 339 const CodeLocation loc = handlers.front()->location; 340 341 ast::FunctionDecl * func_t = ast::deepCopy(catch_func_t); 342 const ast::DeclWithType * index_obj = func_t->params.front(); 343 const ast::DeclWithType * except_obj = func_t->params.back(); 344 345 // Index 1..{number of handlers} 346 int index = 0; 347 CatchList::iterator it = handlers.begin(); 348 for ( ; it != handlers.end() ; ++it ) { 349 ++index; 350 ast::CatchStmt * handler = *it; 351 const CodeLocation loc = handler->location; 352 353 // case `index`: 354 // { 355 // `handler.decl` = { (virtual `decl.type`)`except` }; 356 // `handler.body`; 357 // } 358 // return; 359 ast::CompoundStmt * block = new ast::CompoundStmt(loc); 360 361 // Just copy the exception value. (Post Validation) 362 const ast::ObjectDecl * handler_decl = 363 handler->decl.strict_as<ast::ObjectDecl>(); 364 ast::ObjectDecl * local_except = ast::deepCopy(handler_decl); 365 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 366 new ast::VariableExpr( loc, except_obj ), 367 local_except->get_type() 368 ); 369 vcex->location = handler->location; 370 local_except->init = new ast::ListInit(loc, { new ast::SingleInit( loc, vcex ) }); 371 block->push_back( new ast::DeclStmt( loc, local_except ) ); 372 373 // Add the cleanup attribute. 374 local_except->attributes.push_back( new ast::Attribute( 375 "cleanup", 376 { new ast::NameExpr( loc, "__cfaehm_cleanup_terminate" ) } 377 ) ); 378 379 ast::DeclReplacer::DeclMap mapping; 380 mapping[handler_decl] = local_except; 381 const ast::Stmt * mutBody = strict_dynamic_cast<const ast::Stmt *>( 382 ast::DeclReplacer::replace(handler->body, mapping)); 383 384 385 block->push_back( mutBody ); 386 // handler->body = nullptr; 387 388 handler_wrappers.push_back( new ast::CaseStmt(loc, 389 ast::ConstantExpr::from_int(loc, index) , 390 { block, new ast::ReturnStmt( loc, nullptr ) } 391 )); 392 } 393 // TODO: Some sort of meaningful error on default perhaps? 394 395 /* 396 std::list<Statement*> stmt_handlers; 397 while ( !handler_wrappers.empty() ) { 398 stmt_handlers.push_back( handler_wrappers.front() ); 399 handler_wrappers.pop_front(); 400 } 401 */ 402 403 ast::SwitchStmt * handler_lookup = new ast::SwitchStmt(loc, 404 new ast::VariableExpr( loc, index_obj ), 405 std::move(handler_wrappers) 406 ); 407 ast::CompoundStmt * body = new ast::CompoundStmt(loc, 408 {handler_lookup}); 409 410 func_t->stmts = body; 411 return func_t; 412 } 413 414 // Create a single check from a moddified handler. 415 // except_obj is referenced, modded_handler will be freed. 416 ast::CompoundStmt * TryMutatorCore::create_single_matcher( 417 const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler ) { 418 // { 419 // `modded_handler.decl` 420 // if ( `decl.name = (virtual `decl.type`)`except` 421 // [&& `modded_handler.cond`] ) { 422 // `modded_handler.body` 423 // } 424 // } 425 426 const CodeLocation loc = modded_handler->location; 427 ast::CompoundStmt * block = new ast::CompoundStmt(loc); 428 429 // Local Declaration 430 const ast::ObjectDecl * local_except = 431 modded_handler->decl.strict_as<ast::ObjectDecl>(); 432 block->push_back( new ast::DeclStmt( loc, local_except ) ); 433 434 // Check for type match. 435 ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 436 new ast::VariableExpr(loc, except_obj ), 437 local_except->get_type() 438 ); 439 ast::Expr * cond = ast::UntypedExpr::createAssign(loc, 440 new ast::VariableExpr(loc, local_except ), vcex ); 441 442 // Add the check on the conditional if it is provided. 443 if ( modded_handler->cond ) { 444 cond = new ast::LogicalExpr( loc, cond, modded_handler->cond, ast::LogicalFlag::AndExpr ); 445 } 446 // Construct the match condition. 447 block->push_back( new ast::IfStmt(loc, 448 cond, modded_handler->body, nullptr ) ); 449 450 // xxx - how does this work in new ast 451 //modded_handler->set_decl( nullptr ); 452 //modded_handler->set_cond( nullptr ); 453 //modded_handler->set_body( nullptr ); 454 //delete modded_handler; 455 return block; 456 } 457 458 ast::FunctionDecl * TryMutatorCore::create_terminate_match( 459 CatchList &handlers ) { 460 // int match(exception * except) { 461 // HANDLER WRAPPERS { return `index`; } 462 // } 463 464 assert (!handlers.empty()); 465 const CodeLocation loc = handlers.front()->location; 466 467 ast::CompoundStmt * body = new ast::CompoundStmt(loc); 468 469 ast::FunctionDecl * func_t = ast::deepCopy(match_func_t); 470 const ast::DeclWithType * except_obj = func_t->params.back(); 471 472 // Index 1..{number of handlers} 473 int index = 0; 474 CatchList::iterator it; 475 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) { 476 ++index; 477 ast::CatchStmt * handler = *it; 478 479 // Body should have been taken by create_terminate_catch. 480 // xxx - just ignore it? 481 // assert( nullptr == handler->get_body() ); 482 483 // Create new body. 484 handler->body = new ast::ReturnStmt( handler->location, 485 ast::ConstantExpr::from_int( handler->location, index ) ); 486 487 // Create the handler. 488 body->push_back( create_single_matcher( except_obj, handler ) ); 489 *it = nullptr; 490 } 491 492 body->push_back( new ast::ReturnStmt(loc, 493 ast::ConstantExpr::from_int( loc, 0 ) )); 494 495 func_t->stmts = body; 496 497 return func_t; 498 } 499 500 ast::CompoundStmt * TryMutatorCore::create_terminate_caller( 501 CodeLocation loc, 502 ast::FunctionDecl * try_wrapper, 503 ast::FunctionDecl * terminate_catch, 504 ast::FunctionDecl * terminate_match ) { 505 // { __cfaehm_try_terminate(`try`, `catch`, `match`); } 506 507 ast::UntypedExpr * caller = new ast::UntypedExpr(loc, new ast::NameExpr(loc, 508 "__cfaehm_try_terminate" ) ); 509 caller->args.push_back( new ast::VariableExpr(loc, try_wrapper ) ); 510 caller->args.push_back( new ast::VariableExpr(loc, terminate_catch ) ); 511 caller->args.push_back( new ast::VariableExpr(loc, terminate_match ) ); 512 513 ast::CompoundStmt * callStmt = new ast::CompoundStmt(loc); 514 callStmt->push_back( new ast::ExprStmt( loc, caller ) ); 515 return callStmt; 516 } 517 518 ast::FunctionDecl * TryMutatorCore::create_resume_handler( 519 CatchList &handlers ) { 520 // bool handle(exception * except) { 521 // HANDLER WRAPPERS { `hander->body`; return true; } 522 // } 523 assert (!handlers.empty()); 524 const CodeLocation loc = handlers.front()->location; 525 ast::CompoundStmt * body = new ast::CompoundStmt(loc); 526 527 ast::FunctionDecl * func_t = ast::deepCopy(handle_func_t); 528 const ast::DeclWithType * except_obj = func_t->params.back(); 529 530 CatchList::iterator it; 531 for ( it = handlers.begin() ; it != handlers.end() ; ++it ) { 532 ast::CatchStmt * handler = *it; 533 const CodeLocation loc = handler->location; 534 // Modifiy body. 535 ast::CompoundStmt * handling_code; 536 if (handler->body.as<ast::CompoundStmt>()) { 537 handling_code = 538 strict_dynamic_cast<ast::CompoundStmt*>( handler->body.get_and_mutate() ); 539 } else { 540 handling_code = new ast::CompoundStmt(loc); 541 handling_code->push_back( handler->body ); 542 } 543 handling_code->push_back( new ast::ReturnStmt(loc, 544 ast::ConstantExpr::from_bool(loc, true ) ) ); 545 handler->body = handling_code; 546 547 // Create the handler. 548 body->push_back( create_single_matcher( except_obj, handler ) ); 549 *it = nullptr; 550 } 551 552 body->push_back( new ast::ReturnStmt(loc, 553 ast::ConstantExpr::from_bool(loc, false ) ) ); 554 func_t->stmts = body; 555 556 return func_t; 557 } 558 559 ast::CompoundStmt * TryMutatorCore::create_resume_wrapper( 560 const ast::Stmt * wraps, 561 const ast::FunctionDecl * resume_handler ) { 562 const CodeLocation loc = wraps->location; 563 ast::CompoundStmt * body = new ast::CompoundStmt(loc); 564 565 // struct __try_resume_node __resume_node 566 // __attribute__((cleanup( __cfaehm_try_resume_cleanup ))); 567 // ** unwinding of the stack here could cause problems ** 568 // ** however I don't think that can happen currently ** 569 // __cfaehm_try_resume_setup( &__resume_node, resume_handler ); 570 571 ast::ObjectDecl * obj = new ast::ObjectDecl( 572 loc, 573 "__resume_node", 574 new ast::StructInstType( 575 node_decl 576 ), 577 nullptr, 578 ast::Storage::Classes{}, 579 ast::Linkage::Cforall, 580 nullptr, 581 {new ast::Attribute("cleanup", {new ast::NameExpr(loc, "__cfaehm_try_resume_cleanup")})} 582 ); 583 appendDeclStmt( body, obj ); 584 585 ast::UntypedExpr *setup = new ast::UntypedExpr(loc, new ast::NameExpr(loc, 586 "__cfaehm_try_resume_setup" ) ); 587 setup->args.push_back( new ast::AddressExpr( loc, new ast::VariableExpr(loc, obj ) ) ); 588 setup->args.push_back( new ast::VariableExpr( loc, resume_handler ) ); 589 590 body->push_back( new ast::ExprStmt(loc, setup ) ); 591 592 body->push_back( wraps ); 593 return body; 594 } 595 596 ast::FunctionDecl * TryMutatorCore::create_finally_wrapper( 597 ast::TryStmt * tryStmt ) { 598 // void finally() { `finally->block` } 599 const ast::FinallyStmt * finally = tryStmt->finally; 600 const ast::CompoundStmt * body = finally->body; 601 602 ast::FunctionDecl * func_t = ast::deepCopy(finally_func_t); 603 func_t->stmts = body; 604 605 // finally->set_block( nullptr ); 606 // delete finally; 607 tryStmt->finally = nullptr; 608 609 610 return func_t; 611 } 612 613 ast::ObjectDecl * TryMutatorCore::create_finally_hook( 614 ast::FunctionDecl * finally_wrapper ) { 615 // struct __cfaehm_cleanup_hook __finally_hook 616 // __attribute__((cleanup( `finally_wrapper` ))); 617 618 const CodeLocation loc = finally_wrapper->location; 619 // Make Cleanup Attribute. 620 /* 621 std::list< ast::Attribute * > attributes; 622 { 623 std::list< > attr_params; 624 attr_params.push_back( nameOf( finally_wrapper ) ); 625 attributes.push_back( new Attribute( "cleanup", attr_params ) ); 626 } 627 */ 628 629 return new ast::ObjectDecl( 630 loc, 631 "__finally_hook", 632 new ast::StructInstType( 633 hook_decl 634 ), 635 nullptr, 636 ast::Storage::Classes{}, 637 ast::Linkage::Cforall, 638 nullptr, 639 {new ast::Attribute("cleanup", {new ast::VariableExpr{loc, finally_wrapper}})} 640 ); 641 } 642 643 ast::Stmt * TryMutatorCore::create_resume_rethrow( const ast::ThrowStmt *throwStmt ) { 644 // return false; 645 const CodeLocation loc = throwStmt->location; 646 ast::Stmt * result = new ast::ReturnStmt(loc, 647 ast::ConstantExpr::from_bool( loc, false ) 648 ); 649 result->labels = throwStmt->labels; 650 // delete throwStmt; done by postvisit 651 return result; 652 } 653 654 // Visiting/Mutating Functions 655 void TryMutatorCore::previsit( const ast::StructDecl *structDecl ) { 656 if ( !structDecl->body ) { 657 // Skip children? 658 return; 659 } else if ( structDecl->name == "__cfaehm_base_exception_t" ) { 660 assert( nullptr == except_decl ); 661 except_decl = structDecl; 662 init_func_types(); 663 } else if ( structDecl->name == "__cfaehm_try_resume_node" ) { 664 assert( nullptr == node_decl ); 665 node_decl = structDecl; 666 } else if ( structDecl->name == "__cfaehm_cleanup_hook" ) { 667 assert( nullptr == hook_decl ); 668 hook_decl = structDecl; 669 } 670 } 671 672 ast::Stmt * TryMutatorCore::postvisit( const ast::TryStmt *tryStmt ) { 673 assert( except_decl ); 674 assert( node_decl ); 675 assert( hook_decl ); 676 677 const CodeLocation loc = tryStmt->location; 678 ast::TryStmt * mutStmt = mutate(tryStmt); 679 // Generate a prefix for the function names? 680 681 ast::CompoundStmt * block = new ast::CompoundStmt( loc ); 682 // ast::CompoundStmt * inner = take_try_block( mutStmt ); 683 // this is never mutated so let node deletion do its job? 684 const ast::CompoundStmt * inner = mutStmt->body; 685 686 if ( mutStmt->finally ) { 687 // Define the helper function. 688 ast::FunctionDecl * finally_block = 689 create_finally_wrapper( mutStmt ); 690 appendDeclStmt( block, finally_block ); 691 // Create and add the finally cleanup hook. 692 appendDeclStmt( block, create_finally_hook( finally_block ) ); 693 } 694 695 CatchList termination_handlers; 696 CatchList resumption_handlers; 697 698 for (auto & handler: mutStmt->handlers) { 699 // xxx - should always be unique? mutate as safe const-cast 700 assert(handler->unique()); 701 if (handler->kind == ast::ExceptionKind::Resume) { 702 resumption_handlers.push_back(handler.get_and_mutate()); 703 } 704 else { 705 termination_handlers.push_back(handler.get_and_mutate()); 706 } 707 } 708 // split( mutStmt->handlers, 709 // termination_handlers, resumption_handlers ); 710 711 if ( resumption_handlers.size() ) { 712 // Define the helper function. 713 ast::FunctionDecl * resume_handler = 714 create_resume_handler( resumption_handlers ); 715 appendDeclStmt( block, resume_handler ); 716 // Prepare hooks 717 inner = create_resume_wrapper( inner, resume_handler ); 718 } 719 720 if ( termination_handlers.size() ) { 721 // Define the three helper functions. 722 ast::FunctionDecl * try_wrapper = create_try_wrapper( inner ); 723 appendDeclStmt( block, try_wrapper ); 724 ast::FunctionDecl * terminate_catch = 725 create_terminate_catch( termination_handlers ); 726 appendDeclStmt( block, terminate_catch ); 727 ast::FunctionDecl * terminate_match = 728 create_terminate_match( termination_handlers ); 729 appendDeclStmt( block, terminate_match ); 730 // Build the call to the try wrapper. 731 inner = create_terminate_caller(inner->location, 732 try_wrapper, terminate_catch, terminate_match ); 733 } 734 735 // Embed the try block. 736 block->push_back( inner ); 737 738 return block; 739 } 740 741 ast::Stmt * TryMutatorCore::postvisit( const ast::ThrowStmt *throwStmt ) { 742 // Only valid `throwResume;` statements should remain. (2/3 checks) 743 assert( ast::ExceptionKind::Resume == throwStmt->kind && ! throwStmt->expr ); 744 return create_resume_rethrow( throwStmt ); 745 } 746 747 } // namespace 748 128 749 void translateThrows( ast::TranslationUnit & transUnit ) { 129 750 ast::Pass<TranslateThrowsCore>::run( transUnit ); 751 } 752 753 void translateTries( ast::TranslationUnit & transUnit ) { 754 ast::Pass<TryMutatorCore>::run(transUnit); 130 755 } 131 756 -
src/ControlStruct/MLEMutator.cc
r21a99cc ra554e5f4 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 1 09:26:28202213 // Update Count : 22 512 // Last Modified On : Wed Feb 2 20:18:57 2022 13 // Update Count : 227 14 14 // 15 15 … … 136 136 } 137 137 } 138 assertf( false, "C ould not find label '%s' on statement %s",138 assertf( false, "CFA internal error: could not find label '%s' on statement %s", 139 139 originalTarget.get_name().c_str(), toString( stmt ).c_str() ); 140 140 } … … 395 395 } 396 396 assert( ! enclosingControlStructures.empty() ); 397 assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ), "Control structure enclosing a case clause must be a switch, but is: %s", toCString( enclosingControlStructures.back().get_controlStructure() ) ); 397 assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ), 398 "CFA internal error: control structure enclosing a case clause must be a switch, but is: %s", 399 toCString( enclosingControlStructures.back().get_controlStructure() ) ); 398 400 if ( caseStmt->isDefault() ) { 399 401 if ( enclosingControlStructures.back().isFallDefaultUsed() ) { -
src/ControlStruct/MultiLevelExit.cpp
r21a99cc ra554e5f4 10 10 // Created On : Mon Nov 1 13:48:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 1 18:48:47202213 // Update Count : 2912 // Last Modified On : Wed Feb 2 23:07:54 2022 13 // Update Count : 33 14 14 // 15 15 … … 49 49 return target.label; 50 50 } 51 52 51 public: 53 52 Entry( const ForStmt * stmt, Label breakExit, Label contExit ) : … … 168 167 169 168 // if the stmt is labelled then generate a label to check in postvisit if the label is used 170 bool isLabeled = ! stmt->labels.empty();169 bool isLabeled = ! stmt->labels.empty(); 171 170 if ( isLabeled ) { 172 171 Label breakLabel = newLabel( "blockBreak", stmt ); … … 180 179 181 180 if ( isLabeled ) { 182 assert( ! enclosing_control_structures.empty() );181 assert( ! enclosing_control_structures.empty() ); 183 182 Entry & entry = enclosing_control_structures.back(); 184 if ( ! entry.useBreakExit().empty() ) {183 if ( ! entry.useBreakExit().empty() ) { 185 184 break_label = entry.useBreakExit(); 186 185 } … … 206 205 } 207 206 } 208 assertf( false, "C ould not find label '%s' on statement %s",207 assertf( false, "CFA internal error: could not find label '%s' on statement %s", 209 208 originalTarget.name.c_str(), toString( stmt ).c_str() ); 210 209 } … … 254 253 } 255 254 // Ensure that selected target is valid. 256 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {255 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) { 257 256 SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"), 258 257 " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), … … 268 267 SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" ); 269 268 } 270 if ( ! stmt->target.empty() ) {269 if ( ! stmt->target.empty() ) { 271 270 // Labelled fallthrough: target must be a valid fallthough label. 272 if ( ! fallthrough_labels.count( stmt->target ) ) {271 if ( ! fallthrough_labels.count( stmt->target ) ) { 273 272 SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ", 274 273 stmt->originalTarget ) ); 275 274 } 276 return new BranchStmt( 277 stmt->location, BranchStmt::Goto, stmt->originalTarget ); 275 return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget ); 278 276 } 279 277 break; … … 307 305 } 308 306 309 // Branch error checks: get the appropriate label name: 310 // (This label is always replaced.) 307 // Branch error checks: get the appropriate label name, which is always replaced. 311 308 Label exitLabel( CodeLocation(), "" ); 312 309 switch ( stmt->kind ) { 313 310 case BranchStmt::Break: 314 assert( ! targetEntry->useBreakExit().empty() );311 assert( ! targetEntry->useBreakExit().empty() ); 315 312 exitLabel = targetEntry->useBreakExit(); 316 313 break; 317 314 case BranchStmt::Continue: 318 assert( ! targetEntry->useContExit().empty() );315 assert( ! targetEntry->useContExit().empty() ); 319 316 exitLabel = targetEntry->useContExit(); 320 317 break; 321 318 case BranchStmt::FallThrough: 322 assert( ! targetEntry->useFallExit().empty() );319 assert( ! targetEntry->useFallExit().empty() ); 323 320 exitLabel = targetEntry->useFallExit(); 324 321 break; 325 322 case BranchStmt::FallThroughDefault: 326 assert( ! targetEntry->useFallDefaultExit().empty() );323 assert( ! targetEntry->useFallDefaultExit().empty() ); 327 324 exitLabel = targetEntry->useFallDefaultExit(); 328 325 // Check that fallthrough default comes before the default clause. 329 if ( ! targetEntry->isFallDefaultValid() ) {326 if ( ! targetEntry->isFallDefaultValid() ) { 330 327 SemanticError( stmt->location, "'fallthrough default' must precede the 'default' clause" ); 331 328 } … … 373 370 // If default, mark seen. 374 371 if ( stmt->isDefault() ) { 375 assert( ! enclosing_control_structures.empty() );372 assert( ! enclosing_control_structures.empty() ); 376 373 enclosing_control_structures.back().seenDefault(); 377 374 } … … 399 396 Entry & entry = enclosing_control_structures.back(); 400 397 if ( entry.isFallUsed() ) { 401 mutStmt->stmts.push_back( 402 labelledNullStmt( mutStmt->location, entry.useFallExit() ) ); 398 mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) ); 403 399 } 404 400 } … … 406 402 Entry & entry = enclosing_control_structures.back(); 407 403 assertf( dynamic_cast< const SwitchStmt * >( entry.stmt ), 408 "C ontrol structure enclosing a case clause must be a switch, but is: %s",404 "CFA internal error: control structure enclosing a case clause must be a switch, but is: %s", 409 405 toString( entry.stmt ).c_str() ); 410 406 if ( mutStmt->isDefault() ) { 411 407 if ( entry.isFallDefaultUsed() ) { 412 408 // Add fallthrough default label if necessary. 413 push_front( mutStmt->stmts, labelledNullStmt( 414 stmt->location, entry.useFallDefaultExit() 415 ) ); 409 push_front( mutStmt->stmts, labelledNullStmt( stmt->location, entry.useFallDefaultExit() ) ); 416 410 } 417 411 } … … 420 414 421 415 void MultiLevelExitCore::previsit( const IfStmt * stmt ) { 422 bool labeledBlock = ! stmt->labels.empty();416 bool labeledBlock = ! stmt->labels.empty(); 423 417 if ( labeledBlock ) { 424 418 Label breakLabel = newLabel( "blockBreak", stmt ); … … 429 423 430 424 const IfStmt * MultiLevelExitCore::postvisit( const IfStmt * stmt ) { 431 bool labeledBlock = ! stmt->labels.empty();425 bool labeledBlock = ! stmt->labels.empty(); 432 426 if ( labeledBlock ) { 433 427 auto this_label = enclosing_control_structures.back().useBreakExit(); 434 if ( ! this_label.empty() ) {428 if ( ! this_label.empty() ) { 435 429 break_label = this_label; 436 430 } … … 448 442 auto it = find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase ); 449 443 450 const CaseStmt * defaultCase = it != stmt->stmts.rend() 451 ? (it)->strict_as<CaseStmt>() : nullptr; 452 Label defaultLabel = defaultCase 453 ? newLabel( "fallThroughDefault", defaultCase ) 454 : Label( stmt->location, "" ); 444 const CaseStmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr; 445 Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" ); 455 446 enclosing_control_structures.emplace_back( stmt, label, defaultLabel ); 456 447 GuardAction( [this]() { enclosing_control_structures.pop_back(); } ); 457 448 458 // Collect valid labels for fallthrough. It starts with all labels at 459 // t his level, then remove as each is seen during traversal.449 // Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during 450 // traversal. 460 451 for ( const Stmt * stmt : stmt->stmts ) { 461 452 auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt ); … … 471 462 472 463 const SwitchStmt * MultiLevelExitCore::postvisit( const SwitchStmt * stmt ) { 473 assert( ! enclosing_control_structures.empty() );464 assert( ! enclosing_control_structures.empty() ); 474 465 Entry & entry = enclosing_control_structures.back(); 475 466 assert( entry.stmt == stmt ); … … 477 468 // Only run to generate the break label. 478 469 if ( entry.isBreakUsed() ) { 479 // To keep the switch statements uniform (all direct children of a 480 // SwitchStmt should be CastStmts), append the exit label and break 481 // to the last case, create a default case is there are no cases. 470 // To keep the switch statements uniform (all direct children of a SwitchStmt should be CastStmts), append the 471 // exit label and break to the last case, create a default case if no cases. 482 472 SwitchStmt * mutStmt = mutate( stmt ); 483 473 if ( mutStmt->stmts.empty() ) { 484 mutStmt->stmts.push_back( new CaseStmt( 485 mutStmt->location, nullptr, {} )); 474 mutStmt->stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) ); 486 475 } 487 476 … … 507 496 508 497 void MultiLevelExitCore::previsit( const TryStmt * stmt ) { 509 bool isLabeled = ! stmt->labels.empty();498 bool isLabeled = ! stmt->labels.empty(); 510 499 if ( isLabeled ) { 511 500 Label breakLabel = newLabel( "blockBreak", stmt ); … … 516 505 517 506 void MultiLevelExitCore::postvisit( const TryStmt * stmt ) { 518 bool isLabeled = ! stmt->labels.empty();507 bool isLabeled = ! stmt->labels.empty(); 519 508 if ( isLabeled ) { 520 509 auto this_label = enclosing_control_structures.back().useBreakExit(); 521 if ( ! this_label.empty() ) {510 if ( ! this_label.empty() ) { 522 511 break_label = this_label; 523 512 } … … 526 515 527 516 void MultiLevelExitCore::previsit( const FinallyStmt * ) { 528 GuardAction([this, old = move(enclosing_control_structures)](){ 529 enclosing_control_structures = move(old); 530 }); 517 GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); }); 531 518 enclosing_control_structures = vector<Entry>(); 532 519 GuardValue( inFinally ) = true; … … 575 562 template<typename LoopNode> 576 563 const LoopNode * MultiLevelExitCore::posthandleLoopStmt( const LoopNode * loopStmt ) { 577 assert( ! enclosing_control_structures.empty() );564 assert( ! enclosing_control_structures.empty() ); 578 565 Entry & entry = enclosing_control_structures.back(); 579 566 assert( entry.stmt == loopStmt ); 580 567 581 568 // Now check if the labels are used and add them if so. 582 return mutate_field( 583 loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) ); 569 return mutate_field( loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) ); 584 570 // this call to mutate_field compares loopStmt->body and the result of mutateLoop 585 571 // if they are the same the node isn't mutated, if they differ then the new mutated node is returned … … 609 595 } 610 596 611 if ( !break_label.empty() ) { 612 ret.push_back( 613 labelledNullStmt( ret.back()->location, break_label ) ); 597 if ( ! break_label.empty() ) { 598 ret.push_back( labelledNullStmt( ret.back()->location, break_label ) ); 614 599 break_label = Label( CodeLocation(), "" ); 615 600 } 616 601 } 617 602 618 if ( ! errors.isEmpty() ) {603 if ( ! errors.isEmpty() ) { 619 604 throw errors; 620 605 } -
src/Parser/StatementNode.cc
r21a99cc ra554e5f4 11 11 // Created On : Sat May 16 14:59:41 2015 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Wed Feb 2 12:27:58202214 // Update Count : 42 413 // Last Modified On : Wed Feb 2 20:29:30 2022 14 // Update Count : 425 15 15 // 16 16 … … 138 138 139 139 Statement * build_case( ExpressionNode * ctl ) { 140 return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // no init140 return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to 141 141 } // build_case 142 142 143 143 Statement * build_default() { 144 return new CaseStmt( nullptr, {}, true ); // no init144 return new CaseStmt( nullptr, {}, true ); // stmt starts empty and then added to 145 145 } // build_default 146 146 -
src/SynTree/Statement.cc
r21a99cc ra554e5f4 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 2 11:55:19202213 // Update Count : 8012 // Last Modified On : Wed Feb 2 20:19:33 2022 13 // Update Count : 90 14 14 // 15 15 … … 29 29 #include "SynTree/Label.h" // for Label, operator<< 30 30 31 using std::string;32 using std::endl; 33 34 Statement::Statement( const std::list<Label> & labels ) : labels( labels ) {}35 36 void Statement::print( std::ostream & os, Indenter indent ) const {31 using namespace std; 32 33 34 Statement::Statement( const list<Label> & labels ) : labels( labels ) {} 35 36 void Statement::print( ostream & os, Indenter indent ) const { 37 37 if ( ! labels.empty() ) { 38 38 os << indent << "... Labels: {"; … … 54 54 } 55 55 56 void ExprStmt::print( std::ostream & os, Indenter indent ) const {57 os << "Expression Statement:" << endl << indent +1;58 expr->print( os, indent +1 );59 } 60 61 62 AsmStmt::AsmStmt( bool voltile, Expression * instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}56 void ExprStmt::print( ostream & os, Indenter indent ) const { 57 os << "Expression Statement:" << endl << indent + 1; 58 expr->print( os, indent + 1 ); 59 } 60 61 62 AsmStmt::AsmStmt( bool voltile, Expression * instruction, const list<Expression *> output, const list<Expression *> input, const list<ConstantExpr *> clobber, const list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {} 63 63 64 64 AsmStmt::AsmStmt( const AsmStmt & other ) : Statement( other ), voltile( other.voltile ), instruction( maybeClone( other.instruction ) ), gotolabels( other.gotolabels ) { … … 75 75 } 76 76 77 void AsmStmt::print( std::ostream & os, Indenter indent ) const {77 void AsmStmt::print( ostream & os, Indenter indent ) const { 78 78 os << "Assembler Statement:" << endl; 79 os << indent +1 << "instruction: " << endl << indent;80 instruction->print( os, indent +1 );79 os << indent + 1 << "instruction: " << endl << indent; 80 instruction->print( os, indent + 1 ); 81 81 if ( ! output.empty() ) { 82 os << endl << indent +1 << "output: " << endl;83 printAll( output, os, indent +1 );82 os << endl << indent + 1 << "output: " << endl; 83 printAll( output, os, indent + 1 ); 84 84 } // if 85 85 if ( ! input.empty() ) { 86 os << indent +1 << "input: " << endl;87 printAll( input, os, indent +1 );86 os << indent + 1 << "input: " << endl; 87 printAll( input, os, indent + 1 ); 88 88 } // if 89 89 if ( ! clobber.empty() ) { 90 os << indent +1 << "clobber: " << endl;91 printAll( clobber, os, indent +1 );90 os << indent + 1 << "clobber: " << endl; 91 printAll( clobber, os, indent + 1 ); 92 92 } // if 93 93 } 94 94 95 95 96 DirectiveStmt::DirectiveStmt( const st d::string & directive ) : Statement(), directive( directive ) {}97 98 void DirectiveStmt::print( std::ostream & os, Indenter ) const {96 DirectiveStmt::DirectiveStmt( const string & directive ) : Statement(), directive( directive ) {} 97 98 void DirectiveStmt::print( ostream & os, Indenter ) const { 99 99 os << "GCC Directive:" << directive << endl; 100 100 } … … 120 120 } 121 121 122 void BranchStmt::print( std::ostream & os, Indenter indent ) const {123 assert (type < 5);122 void BranchStmt::print( ostream & os, Indenter indent ) const { 123 assertf(type < BranchStmts, "CFA internal error: invalid branch statement" ); 124 124 os << "Branch (" << brType[type] << ")" << endl ; 125 if ( target != "" ) os << indent +1 << "with target: " << target << endl;126 if ( originalTarget != "" ) os << indent +1 << "with original target: " << originalTarget << endl;127 if ( computedTarget != nullptr ) os << indent +1 << "with computed target: " << computedTarget << endl;125 if ( target != "" ) os << indent + 1 << "with target: " << target << endl; 126 if ( originalTarget != "" ) os << indent + 1 << "with original target: " << originalTarget << endl; 127 if ( computedTarget != nullptr ) os << indent + 1 << "with computed target: " << computedTarget << endl; 128 128 } 129 129 … … 136 136 } 137 137 138 void ReturnStmt::print( std::ostream & os, Indenter indent ) const {138 void ReturnStmt::print( ostream & os, Indenter indent ) const { 139 139 os << "Return Statement, returning: "; 140 140 if ( expr != nullptr ) { 141 os << endl << indent +1;142 expr->print( os, indent +1 );141 os << endl << indent + 1; 142 expr->print( os, indent + 1 ); 143 143 } 144 144 os << endl; 145 145 } 146 146 147 IfStmt::IfStmt( Expression * condition, Statement * then, Statement * else_, std::list<Statement *> initialization ):147 IfStmt::IfStmt( Expression * condition, Statement * then, Statement * else_, const list<Statement *> initialization ): 148 148 Statement(), condition( condition ), then( then ), else_( else_ ), initialization( initialization ) {} 149 149 … … 160 160 } 161 161 162 void IfStmt::print( std::ostream & os, Indenter indent ) const {162 void IfStmt::print( ostream & os, Indenter indent ) const { 163 163 os << "If on condition: " << endl; 164 os << indent +1;165 condition->print( os, indent +1 );164 os << indent + 1; 165 condition->print( os, indent + 1 ); 166 166 167 167 if ( !initialization.empty() ) { 168 168 os << indent << "... with initialization: \n"; 169 169 for ( const Statement * stmt : initialization ) { 170 os << indent +1;171 stmt->print( os, indent +1 );170 os << indent + 1; 171 stmt->print( os, indent + 1 ); 172 172 } 173 173 os << endl; … … 176 176 os << indent << "... then: " << endl; 177 177 178 os << indent +1;179 then->print( os, indent +1 );178 os << indent + 1; 179 then->print( os, indent + 1 ); 180 180 181 181 if ( else_ != nullptr ) { 182 182 os << indent << "... else: " << endl; 183 os << indent +1;184 else_->print( os, indent +1 );183 os << indent + 1; 184 else_->print( os, indent + 1 ); 185 185 } // if 186 186 } 187 187 188 SwitchStmt::SwitchStmt( Expression * condition, const std::list<Statement *> & statements ):188 SwitchStmt::SwitchStmt( Expression * condition, const list<Statement *> & statements ): 189 189 Statement(), condition( condition ), statements( statements ) { 190 190 } … … 201 201 } 202 202 203 void SwitchStmt::print( std::ostream & os, Indenter indent ) const {203 void SwitchStmt::print( ostream & os, Indenter indent ) const { 204 204 os << "Switch on condition: "; 205 205 condition->print( os ); … … 207 207 208 208 for ( const Statement * stmt : statements ) { 209 stmt->print( os, indent +1 );210 } 211 } 212 213 CaseStmt::CaseStmt( Expression * condition, const std::list<Statement *> & statements, bool deflt ) throw ( SemanticErrorException ) :214 Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {209 stmt->print( os, indent + 1 ); 210 } 211 } 212 213 CaseStmt::CaseStmt( Expression * condition, const list<Statement *> & statements, bool deflt ) throw ( SemanticErrorException ) : 214 Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) { 215 215 if ( isDefault() && condition != nullptr ) SemanticError( condition, "default case with condition: " ); 216 216 } 217 217 218 218 CaseStmt::CaseStmt( const CaseStmt & other ) : 219 Statement( other ), condition( maybeClone(other.condition ) ), _isDefault( other._isDefault ) {219 Statement( other ), condition( maybeClone(other.condition ) ), _isDefault( other._isDefault ) { 220 220 cloneAll( other.stmts, stmts ); 221 221 } … … 226 226 } 227 227 228 CaseStmt * CaseStmt::makeDefault( const std::list<Label> & labels, std::list<Statement *> stmts ) {228 CaseStmt * CaseStmt::makeDefault( const list<Label> & labels, list<Statement *> stmts ) { 229 229 CaseStmt * stmt = new CaseStmt( nullptr, stmts, true ); 230 230 stmt->labels = labels; … … 232 232 } 233 233 234 void CaseStmt::print( std::ostream & os, Indenter indent ) const {234 void CaseStmt::print( ostream & os, Indenter indent ) const { 235 235 if ( isDefault() ) os << indent << "Default "; 236 236 else { … … 241 241 242 242 for ( Statement * stmt : stmts ) { 243 os << indent +1;244 stmt->print( os, indent +1 );245 } 246 } 247 248 WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, const std::list< Statement * > & initialization, bool isDoWhile ):243 os << indent + 1; 244 stmt->print( os, indent + 1 ); 245 } 246 } 247 248 WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, const list< Statement * > & initialization, bool isDoWhile ): 249 249 Statement(), condition( condition ), body( body ), else_( nullptr ), initialization( initialization ), isDoWhile( isDoWhile) { 250 250 } 251 251 252 WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const std::list< Statement * > & initialization, bool isDoWhile ):252 WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const list< Statement * > & initialization, bool isDoWhile ): 253 253 Statement(), condition( condition), body( body ), else_( else_ ), initialization( initialization ), isDoWhile( isDoWhile) { 254 254 } … … 263 263 } 264 264 265 void WhileDoStmt::print( std::ostream & os, Indenter indent ) const {265 void WhileDoStmt::print( ostream & os, Indenter indent ) const { 266 266 os << "While on condition: " << endl ; 267 condition->print( os, indent +1 );267 condition->print( os, indent + 1 ); 268 268 269 269 os << indent << "... with body: " << endl; 270 270 271 if ( body != nullptr ) body->print( os, indent +1 );272 } 273 274 ForStmt::ForStmt( std::list<Statement *> initialization, Expression * condition, Expression * increment, Statement * body, Statement * else_ ):271 if ( body != nullptr ) body->print( os, indent + 1 ); 272 } 273 274 ForStmt::ForStmt( const list<Statement *> initialization, Expression * condition, Expression * increment, Statement * body, Statement * else_ ): 275 275 Statement(), initialization( initialization ), condition( condition ), increment( increment ), body( body ), else_( else_ ) { 276 276 } … … 290 290 } 291 291 292 void ForStmt::print( std::ostream & os, Indenter indent ) const {292 void ForStmt::print( ostream & os, Indenter indent ) const { 293 293 Statement::print( os, indent ); // print labels 294 294 … … 298 298 os << indent << "... initialization: \n"; 299 299 for ( Statement * stmt : initialization ) { 300 os << indent +1;301 stmt->print( os, indent +1 );300 os << indent + 1; 301 stmt->print( os, indent + 1 ); 302 302 } 303 303 } 304 304 305 305 if ( condition != nullptr ) { 306 os << indent << "... condition: \n" << indent +1;307 condition->print( os, indent +1 );306 os << indent << "... condition: \n" << indent + 1; 307 condition->print( os, indent + 1 ); 308 308 } 309 309 310 310 if ( increment != nullptr ) { 311 os << "\n" << indent << "... increment: \n" << indent +1;312 increment->print( os, indent +1 );311 os << "\n" << indent << "... increment: \n" << indent + 1; 312 increment->print( os, indent + 1 ); 313 313 } 314 314 315 315 if ( body != nullptr ) { 316 os << "\n" << indent << "... with body: \n" << indent +1;317 body->print( os, indent +1 );316 os << "\n" << indent << "... with body: \n" << indent + 1; 317 body->print( os, indent + 1 ); 318 318 } 319 319 320 320 if ( else_ != nullptr ) { 321 os << "\n" << indent << "... with body: \n" << indent +1;322 else_->print( os, indent +1 );321 os << "\n" << indent << "... with body: \n" << indent + 1; 322 else_->print( os, indent + 1 ); 323 323 } 324 324 os << endl; … … 339 339 } 340 340 341 void ThrowStmt::print( std::ostream & os, Indenter indent) const {341 void ThrowStmt::print( ostream & os, Indenter indent) const { 342 342 if ( target ) os << "Non-Local "; 343 343 os << "Throw Statement, raising: "; 344 expr->print(os, indent +1);344 expr->print(os, indent + 1); 345 345 if ( target ) { 346 346 os << "... at: "; 347 target->print(os, indent +1);348 } 349 } 350 351 TryStmt::TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock ) :347 target->print(os, indent + 1); 348 } 349 } 350 351 TryStmt::TryStmt( CompoundStmt * tryBlock, const list<CatchStmt *> & handlers, FinallyStmt * finallyBlock ) : 352 352 Statement(), block( tryBlock ), handlers( handlers ), finallyBlock( finallyBlock ) { 353 353 } … … 363 363 } 364 364 365 void TryStmt::print( std::ostream & os, Indenter indent ) const {365 void TryStmt::print( ostream & os, Indenter indent ) const { 366 366 os << "Try Statement" << endl; 367 os << indent << "... with block:" << endl << indent +1;368 block->print( os, indent +1 );367 os << indent << "... with block:" << endl << indent + 1; 368 block->print( os, indent + 1 ); 369 369 370 370 // handlers 371 371 os << indent << "... and handlers:" << endl; 372 372 for ( const CatchStmt * stmt : handlers ) { 373 os << indent +1;374 stmt->print( os, indent +1 );373 os << indent + 1; 374 stmt->print( os, indent + 1 ); 375 375 } 376 376 377 377 // finally block 378 378 if ( finallyBlock != nullptr ) { 379 os << indent << "... and finally:" << endl << indent +1;380 finallyBlock->print( os, indent +1 );379 os << indent << "... and finally:" << endl << indent + 1; 380 finallyBlock->print( os, indent + 1 ); 381 381 } // if 382 382 } … … 396 396 } 397 397 398 void CatchStmt::print( std::ostream & os, Indenter indent ) const {398 void CatchStmt::print( ostream & os, Indenter indent ) const { 399 399 os << "Catch " << ((Terminate == kind) ? "Terminate" : "Resume") << " Statement" << endl; 400 400 401 401 os << indent << "... catching: "; 402 decl->printShort( os, indent +1 );402 decl->printShort( os, indent + 1 ); 403 403 os << endl; 404 404 405 405 if ( cond ) { 406 os << indent << "... with conditional:" << endl << indent +1;407 cond->print( os, indent +1 );406 os << indent << "... with conditional:" << endl << indent + 1; 407 cond->print( os, indent + 1 ); 408 408 } 409 409 410 410 os << indent << "... with block:" << endl; 411 os << indent +1;412 body->print( os, indent +1 );411 os << indent + 1; 412 body->print( os, indent + 1 ); 413 413 } 414 414 … … 424 424 } 425 425 426 void FinallyStmt::print( std::ostream & os, Indenter indent ) const {426 void FinallyStmt::print( ostream & os, Indenter indent ) const { 427 427 os << "Finally Statement" << endl; 428 os << indent << "... with block:" << endl << indent +1;429 block->print( os, indent +1 );428 os << indent << "... with block:" << endl << indent + 1; 429 block->print( os, indent + 1 ); 430 430 } 431 431 … … 439 439 } 440 440 441 void SuspendStmt::print( std::ostream & os, Indenter indent ) const {441 void SuspendStmt::print( ostream & os, Indenter indent ) const { 442 442 os << "Suspend Statement"; 443 443 switch (type) { … … 496 496 } 497 497 498 void WaitForStmt::print( std::ostream & os, Indenter indent ) const {498 void WaitForStmt::print( ostream & os, Indenter indent ) const { 499 499 os << "Waitfor Statement" << endl; 500 500 indent += 1; … … 531 531 532 532 533 WithStmt::WithStmt( const std::list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {}533 WithStmt::WithStmt( const list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {} 534 534 WithStmt::WithStmt( const WithStmt & other ) : Declaration( other ), stmt( maybeClone( other.stmt ) ) { 535 535 cloneAll( other.exprs, exprs ); … … 540 540 } 541 541 542 void WithStmt::print( std::ostream & os, Indenter indent ) const {542 void WithStmt::print( ostream & os, Indenter indent ) const { 543 543 os << "With statement" << endl; 544 544 os << indent << "... with expressions: " << endl; 545 printAll( exprs, os, indent +1 );546 os << indent << "... with statement:" << endl << indent +1;547 stmt->print( os, indent +1 );548 } 549 550 551 NullStmt::NullStmt( const std::list<Label> & labels ) : Statement( labels ) {552 } 553 554 void NullStmt::print( std::ostream & os, Indenter indent ) const {545 printAll( exprs, os, indent + 1 ); 546 os << indent << "... with statement:" << endl << indent + 1; 547 stmt->print( os, indent + 1 ); 548 } 549 550 551 NullStmt::NullStmt( const list<Label> & labels ) : Statement( labels ) { 552 } 553 554 void NullStmt::print( ostream & os, Indenter indent ) const { 555 555 os << "Null Statement" << endl; 556 556 Statement::print( os, indent ); … … 568 568 } 569 569 570 void ImplicitCtorDtorStmt::print( std::ostream & os, Indenter indent ) const {570 void ImplicitCtorDtorStmt::print( ostream & os, Indenter indent ) const { 571 571 os << "Implicit Ctor Dtor Statement" << endl; 572 572 os << indent << "... with Ctor/Dtor: "; 573 callStmt->print( os, indent +1);573 callStmt->print( os, indent + 1); 574 574 os << endl; 575 575 } 576 576 577 MutexStmt::MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs )577 MutexStmt::MutexStmt( Statement * stmt, const list<Expression *> mutexObjs ) 578 578 : Statement(), stmt( stmt ), mutexObjs( mutexObjs ) { } 579 579 … … 587 587 } 588 588 589 void MutexStmt::print( std::ostream & os, Indenter indent ) const {589 void MutexStmt::print( ostream & os, Indenter indent ) const { 590 590 os << "Mutex Statement" << endl; 591 591 os << indent << "... with Expressions: " << endl; 592 592 for (auto * obj : mutexObjs) { 593 os << indent +1;594 obj->print( os, indent +1);593 os << indent + 1; 594 obj->print( os, indent + 1); 595 595 os << endl; 596 596 } 597 os << indent << "... with Statement: " << endl << indent +1;598 stmt->print( os, indent +1 );597 os << indent << "... with Statement: " << endl << indent + 1; 598 stmt->print( os, indent + 1 ); 599 599 } 600 600 -
src/SynTree/Statement.h
r21a99cc ra554e5f4 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Feb 2 11:49:17202213 // Update Count : 9 412 // Last Modified On : Wed Feb 2 20:15:30 2022 13 // Update Count : 98 14 14 // 15 15 … … 107 107 std::list<Label> gotolabels; 108 108 109 AsmStmt( bool voltile, Expression * instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber,std::list<Label> gotolabels );109 AsmStmt( bool voltile, Expression * instruction, const std::list<Expression *> output, const std::list<Expression *> input, const std::list<ConstantExpr *> clobber, const std::list<Label> gotolabels ); 110 110 AsmStmt( const AsmStmt & other ); 111 111 virtual ~AsmStmt(); … … 153 153 154 154 IfStmt( Expression * condition, Statement * then, Statement * else_, 155 std::list<Statement *> initialization = std::list<Statement *>() );155 const std::list<Statement *> initialization = std::list<Statement *>() ); 156 156 IfStmt( const IfStmt & other ); 157 157 virtual ~IfStmt(); … … 260 260 Statement * else_; 261 261 262 ForStmt( std::list<Statement *> initialization, Expression * condition = nullptr, Expression * increment = nullptr, Statement * body = nullptr, Statement * else_ = nullptr );262 ForStmt( const std::list<Statement *> initialization, Expression * condition = nullptr, Expression * increment = nullptr, Statement * body = nullptr, Statement * else_ = nullptr ); 263 263 ForStmt( const ForStmt & other ); 264 264 virtual ~ForStmt(); … … 281 281 class BranchStmt : public Statement { 282 282 public: 283 enum Type { Goto = 0, Break, Continue, FallThrough, FallThroughDefault};283 enum Type { Goto, Break, Continue, FallThrough, FallThroughDefault, BranchStmts }; 284 284 285 285 // originalTarget kept for error messages. … … 360 360 FinallyStmt * finallyBlock; 361 361 362 TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = nullptr );362 TryStmt( CompoundStmt * tryBlock, const std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = nullptr ); 363 363 TryStmt( const TryStmt & other ); 364 364 virtual ~TryStmt(); … … 543 543 std::list<Expression *> mutexObjs; // list of mutex objects to acquire 544 544 545 MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs );545 MutexStmt( Statement * stmt, const std::list<Expression *> mutexObjs ); 546 546 MutexStmt( const MutexStmt & other ); 547 547 virtual ~MutexStmt(); -
src/main.cc
r21a99cc ra554e5f4 415 415 // Currently not working due to unresolved issues with UniqueExpr 416 416 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused 417 418 PASS( "Translate Tries" , ControlStruct::translateTries( transUnit ) ); 419 417 420 translationUnit = convert( move( transUnit ) ); 418 421 } else { … … 481 484 482 485 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused 486 487 PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) ); 483 488 } 484 489 485 PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );490 486 491 487 492 PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) ); -
tests/include/.expect/includes.nast.txt
r21a99cc ra554e5f4 1 include/includes.cfa:15 4:25: warning: Compiled1 include/includes.cfa:153:25: warning: Compiled -
tests/include/includes.cfa
r21a99cc ra554e5f4 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 5 10:06:46 202113 // Update Count : 7 5112 // Last Modified On : Thu Feb 3 22:06:07 2022 13 // Update Count : 774 14 14 // 15 15 … … 18 18 #endif // __CFA__ 19 19 20 #if 1 20 21 //#define _GNU_SOURCE 21 22 #include <aio.h> … … 40 41 #include <errno.h> 41 42 #include <error.h> 42 //#include <eti.h> 43 //#include <eti.h> // may not be installed, comes with ncurses 43 44 #include <execinfo.h> 44 45 #include <expat.h> … … 49 50 #include <fmtmsg.h> 50 51 #include <fnmatch.h> 51 //#include <form.h> 52 //#include <form.h> // may not be installed, comes with ncurses 52 53 #include <fstab.h> 53 54 #include <fts.h> … … 77 78 #include <mcheck.h> 78 79 #include <memory.h> 79 //#include <menu.h> 80 //#include <menu.h> // may not be installed, comes with ncurses 80 81 #include <mntent.h> 81 82 #include <monetary.h> 82 83 #include <mqueue.h> 83 //#include <ncurses_dll.h> 84 //#include <ncurses_dll.h> // may not be installed, comes with ncurses 84 85 #include <netdb.h> 85 86 #include <nl_types.h> 86 87 #include <nss.h> 87 88 #include <obstack.h> 88 //#include <panel.h> 89 //#include <panel.h> // may not be installed, comes with ncurses 89 90 #include <paths.h> 90 91 #include <poll.h> … … 117 118 #include <syslog.h> 118 119 #include <tar.h> 119 //#include <term.h> 120 //#include <termcap.h> 120 //#include <term.h> // may not be installed, comes with ncurses 121 //#include <termcap.h> // may not be installed, comes with ncurses 121 122 #include <termio.h> 122 123 #include <termios.h> … … 130 131 #include <ucontext.h> 131 132 #include <ulimit.h> 132 //#include <unctrl.h> 133 //#include <unctrl.h> // may not be installed, comes with ncurses 133 134 #include <unistd.h> 134 135 #include <utime.h> … … 143 144 #include <wctype.h> 144 145 #include <wordexp.h> 145 146 #if 0147 146 #endif // 0 148 147 … … 151 150 #endif // __CFA__ 152 151 153 int main( int argc, char const * argv[] ) {154 #pragma GCC warning "Compiled" 152 int main( int argc, char const * argv[] ) { 153 #pragma GCC warning "Compiled" // force non-empty .expect file, NO TABS!!! 155 154 } 156 155
Note: See TracChangeset
for help on using the changeset viewer.