Changeset 6e1e2d0
- Timestamp:
- May 1, 2023, 4:19:09 PM (2 years ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- c083c3d
- Parents:
- a50fdfb (diff), 985b624 (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:
-
- 7 added
- 1 deleted
- 86 edited
Legend:
- Unmodified
- Added
- Removed
-
Jenkins/FullBuild
ra50fdfb r6e1e2d0 20 20 gcc_08_x86_new: { trigger_build( 'gcc-10', 'x86', false ) }, 21 21 gcc_07_x86_new: { trigger_build( 'gcc-9', 'x86', false ) }, 22 gcc_11_x64_new: { trigger_build( 'gcc-11', 'x64', false ) }, 22 23 gcc_10_x64_new: { trigger_build( 'gcc-10', 'x64', false ) }, 23 24 gcc_09_x64_new: { trigger_build( 'gcc-9', 'x64', false ) }, 24 25 gcc_08_x64_new: { trigger_build( 'gcc-8', 'x64', false ) }, 25 26 gcc_07_x64_new: { trigger_build( 'gcc-7', 'x64', false ) }, 26 gcc_06_x64_new: { trigger_build( 'gcc-6', 'x64', false ) },27 // gcc_06_x64_new: { trigger_build( 'gcc-6', 'x64', false ) }, 27 28 clang_x64_new: { trigger_build( 'clang', 'x64', true ) }, 28 29 ) … … 41 42 } 42 43 43 // If an exception is caught we need to change the status and remember to44 // attach the build log to the email44 // If an exception is caught we need to change the status and remember to 45 // attach the build log to the email 45 46 catch (Exception caughtError) { 46 47 echo('error caught') … … 73 74 // Run the build 74 75 // Don't propagate, it doesn't play nice with our email setup 75 def result = build job: 'Cforall/master', \76 def result = build job: 'Cforall/master', \ 76 77 parameters: [ \ 77 78 [$class: 'StringParameterValue', \ … … 83 84 [$class: 'BooleanParameterValue', \ 84 85 name: 'NewAST', \ 85 value: true], 86 value: true], \ 86 87 [$class: 'BooleanParameterValue', \ 87 88 name: 'RunAllTests', \ 88 value: true], 89 value: true], \ 89 90 [$class: 'BooleanParameterValue', \ 90 91 name: 'RunBenchmark', \ 91 value: true], 92 value: true], \ 92 93 [$class: 'BooleanParameterValue', \ 93 name: 'BuildDocumentation', \94 name: 'BuildDocumentation', \ 94 95 value: doc], \ 95 96 [$class: 'BooleanParameterValue', \ 96 97 name: 'Publish', \ 97 value: true], 98 value: true], \ 98 99 [$class: 'BooleanParameterValue', \ 99 100 name: 'Silent', \ 100 value: true], 101 ], 101 value: true], \ 102 ], \ 102 103 propagate: false 103 104 … … 111 112 112 113 def trigger_dist(String commitId, String buildNum) { 113 def result = build job: 'Cforall_Distribute_Ref', \114 def result = build job: 'Cforall_Distribute_Ref', \ 114 115 parameters: [ \ 115 116 string(name: 'GitRef', value: commitId), \ 116 string(name: 'Build' , value: buildNum) \117 ], 117 string(name: 'Build' , value: buildNum) \ 118 ], \ 118 119 propagate: false 119 120 -
Jenkinsfile
ra50fdfb r6e1e2d0 305 305 this.Compiler = new CC_Desc('gcc-7', 'g++-7', 'gcc-7', '-flto=auto') 306 306 break 307 case 'gcc-6':308 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto')309 break310 case 'gcc-5':311 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto')312 break313 case 'gcc-4.9':314 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto')315 break307 // case 'gcc-6': 308 // this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6', '-flto=auto') 309 // break 310 // case 'gcc-5': 311 // this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5', '-flto=auto') 312 // break 313 // case 'gcc-4.9': 314 // this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9', '-flto=auto') 315 // break 316 316 case 'clang': 317 317 this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-10', '-flto=thin -flto-jobs=0') … … 359 359 def prepare_build() { 360 360 // prepare the properties 361 properties ([ 362 buildDiscarder(logRotator( 363 artifactDaysToKeepStr: '', 364 artifactNumToKeepStr: '', 365 daysToKeepStr: '730', 366 numToKeepStr: '1000' 367 )), 368 [$class: 'ParametersDefinitionProperty', 369 parameterDefinitions: [ 370 [$class: 'ChoiceParameterDefinition', 371 description: 'Which compiler to use', 372 name: 'Compiler', 373 choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\n gcc-6\ngcc-5\ngcc-4.9\nclang', \374 defaultValue: 'gcc- 8',\375 ], 376 [$class: 'ChoiceParameterDefinition', 377 description: 'The target architecture', 378 name: 'Architecture', 379 choices: 'x64\nx86', 380 defaultValue: 'x64', 381 ], 382 [$class: 'BooleanParameterDefinition', 361 properties ([ \ 362 buildDiscarder(logRotator( \ 363 artifactDaysToKeepStr: '', \ 364 artifactNumToKeepStr: '', \ 365 daysToKeepStr: '730', \ 366 numToKeepStr: '1000' \ 367 )), \ 368 [$class: 'ParametersDefinitionProperty', \ 369 parameterDefinitions: [ \ 370 [$class: 'ChoiceParameterDefinition', \ 371 description: 'Which compiler to use', \ 372 name: 'Compiler', \ 373 choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\nclang', \ 374 defaultValue: 'gcc-9', \ 375 ], \ 376 [$class: 'ChoiceParameterDefinition', \ 377 description: 'The target architecture', \ 378 name: 'Architecture', \ 379 choices: 'x64\nx86', \ 380 defaultValue: 'x64', \ 381 ], \ 382 [$class: 'BooleanParameterDefinition', \ 383 383 description: 'If false, the test suite is only ran in debug', \ 384 name: 'RunAllTests', 385 defaultValue: false, 386 ], 387 [$class: 'BooleanParameterDefinition', 388 description: 'If true, jenkins also runs benchmarks', 389 name: 'RunBenchmark', 390 defaultValue: false, 391 ], 392 [$class: 'BooleanParameterDefinition', 393 description: 'If true, jenkins also builds documentation', 394 name: 'BuildDocumentation', 395 defaultValue: true, 396 ], 397 [$class: 'BooleanParameterDefinition', 398 description: 'If true, jenkins also publishes results', 399 name: 'Publish', 400 defaultValue: false, 401 ], 402 [$class: 'BooleanParameterDefinition', 403 description: 'If true, jenkins will not send emails', 404 name: 'Silent', 405 defaultValue: false, 406 ], 384 name: 'RunAllTests', \ 385 defaultValue: false, \ 386 ], \ 387 [$class: 'BooleanParameterDefinition', \ 388 description: 'If true, jenkins also runs benchmarks', \ 389 name: 'RunBenchmark', \ 390 defaultValue: false, \ 391 ], \ 392 [$class: 'BooleanParameterDefinition', \ 393 description: 'If true, jenkins also builds documentation', \ 394 name: 'BuildDocumentation', \ 395 defaultValue: true, \ 396 ], \ 397 [$class: 'BooleanParameterDefinition', \ 398 description: 'If true, jenkins also publishes results', \ 399 name: 'Publish', \ 400 defaultValue: false, \ 401 ], \ 402 [$class: 'BooleanParameterDefinition', \ 403 description: 'If true, jenkins will not send emails', \ 404 name: 'Silent', \ 405 defaultValue: false, \ 406 ], \ 407 407 ], 408 408 ]]) 409 // choices: 'gcc-11\ngcc-10\ngcc-9\ngcc-8\ngcc-7\ngcc-6\ngcc-5\ngcc-4.9\nclang', 410 // defaultValue: 'gcc-8', 409 411 410 412 // It's unfortunate but it looks like we need to checkout the entire repo just to get -
doc/bibliography/pl.bib
ra50fdfb r6e1e2d0 7453 7453 } 7454 7454 7455 @inproceedings{Kahn74, 7456 keywords = {programming language, obect-oriented, polymorphism}, 7457 contributer = {pabuhr@plg}, 7458 title = {The Semantics of a Simple Language for Parallel Programming}, 7459 author = {Gilles Kahn}, 7460 booktitle = {IFIP Congress}, 7461 year = 1974, 7462 } 7463 7455 7464 @article{Baker78, 7456 7465 keywords = {Algol display, FUNARG's, Lisp 1.5, deep binding, environment trees, multiprogramming, shallow binding}, -
doc/theses/colby_parsons_MMAth/.gitignore
ra50fdfb r6e1e2d0 1 build/*.aux 2 build/*.acn 3 build/*.acr 4 build/*.alg 5 build/*.bbl 6 build/*.blg 7 build/*.brf 8 build/*.dvi 9 build/*.glg 10 build/*.glo 11 build/*.gls 12 build/*.idx 13 build/*.ind 14 build/*.ist 15 build/*.lof 16 build/*.log 17 build/*.lol 18 build/*.lot 19 build/*.out 20 build/*.ps 21 build/*.pstex 22 build/*.pstex_t 23 build/*.tex 24 build/*.toc 1 # Intermediate Results: 2 build/ 3 4 # Final Files: 25 5 *.pdf 26 *.png27 6 *.ps 28 figures/*.tex29 7 30 examples 8 # The Makefile here is not generated. 9 !Makefile -
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_CFA.txt
ra50fdfb r6e1e2d0 1 1 5 2 2 1 2 4 8 16 24 32 48 3 CFA-LV CFA-NS CFA-R3 Longest-Victim No-Stealing Random 4 4 executor 5 CFA-LV:5 Longest-Victim: 6 6 proc time (s) 7 7 1 29.22 … … 45 45 48 1.20 46 46 48 1.20 47 CFA-NS:47 No-Stealing: 48 48 proc time (s) 49 49 1 28.25 … … 87 87 48 1.18 88 88 48 1.16 89 CFA-R:89 Random: 90 90 proc time (s) 91 91 1 28.58 … … 131 131 132 132 matrix 133 CFA-LV:133 Longest-Victim: 134 134 proc time (s) 135 135 1 105.48 … … 173 173 48 2.75 174 174 48 2.96 175 CFA-NS:175 No-Stealing: 176 176 proc time (s) 177 177 1 106.01 … … 215 215 48 2.78 216 216 48 2.92 217 CFA-R:217 Random: 218 218 proc time (s) 219 219 1 105.91 … … 259 259 260 260 repeat 261 CFA-LV:261 Longest-Victim: 262 262 proc time (s) 263 263 1 1.17 … … 301 301 48 13.73 302 302 48 14.55 303 CFA-NS:303 No-Stealing: 304 304 proc time (s) 305 305 1 1.15 … … 343 343 48 13.03 344 344 48 12.83 345 CFA-R:345 Random: 346 346 proc time (s) 347 347 1 1.15 … … 387 387 388 388 balance_one 389 CFA-LV:389 Longest-Victim: 390 390 proc time (s) 391 391 1 20.06 … … 429 429 48 1.11 430 430 48 1.12 431 CFA-NS:431 No-Stealing: 432 432 proc time (s) 433 433 1 20.13 … … 471 471 48 19.95 472 472 48 20.00 473 CFA-R:473 Random: 474 474 proc time (s) 475 475 1 19.92 … … 515 515 516 516 balance_multi 517 CFA-LV:517 Longest-Victim: 518 518 proc time (s) 519 519 1 8.17 … … 557 557 48 5.75 558 558 48 5.68 559 CFA-NS:559 No-Stealing: 560 560 proc time (s) 561 561 1 8.10 … … 599 599 48 9.28 600 600 48 9.26 601 CFA-R:601 Random: 602 602 proc time (s) 603 603 1 8.08 -
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_CFA.txt
ra50fdfb r6e1e2d0 1 1 5 2 2 1 2 4 8 16 24 32 48 3 CFA-LV CFA-NS CFA-R3 Longest-Victim No-Stealing Random 4 4 executor 5 CFA-LV:5 Longest-Victim: 6 6 proc time (s) 7 7 1 29.04 … … 45 45 48 2.58 46 46 48 2.55 47 CFA-NS:47 No-Stealing: 48 48 proc time (s) 49 49 1 28.15 … … 87 87 48 2.59 88 88 48 2.60 89 CFA-R:89 Random: 90 90 proc time (s) 91 91 1 29.06 … … 131 131 132 132 matrix 133 CFA-LV:133 Longest-Victim: 134 134 proc time (s) 135 135 1 127.44 … … 173 173 48 6.83 174 174 48 6.81 175 CFA-NS:175 No-Stealing: 176 176 proc time (s) 177 177 1 127.64 … … 215 215 48 6.77 216 216 48 6.74 217 CFA-R:217 Random: 218 218 proc time (s) 219 219 1 127.26 … … 259 259 260 260 repeat 261 CFA-LV:261 Longest-Victim: 262 262 proc time (s) 263 263 1 1.16 … … 301 301 48 19.75 302 302 48 19.71 303 CFA-NS:303 No-Stealing: 304 304 proc time (s) 305 305 1 1.18 … … 343 343 48 13.88 344 344 48 13.71 345 CFA-R:345 Random: 346 346 proc time (s) 347 347 1 1.18 … … 387 387 388 388 balance_one 389 CFA-LV:389 Longest-Victim: 390 390 proc time (s) 391 391 1 19.46 … … 429 429 48 2.12 430 430 48 2.17 431 CFA-NS:431 No-Stealing: 432 432 proc time (s) 433 433 1 21.00 … … 471 471 48 47.50 472 472 48 47.72 473 CFA-R:473 Random: 474 474 proc time (s) 475 475 1 20.81 … … 515 515 516 516 balance_multi 517 CFA-LV:517 Longest-Victim: 518 518 proc time (s) 519 519 1 7.94 … … 557 557 48 14.38 558 558 48 14.50 559 CFA-NS:559 No-Stealing: 560 560 proc time (s) 561 561 1 8.48 … … 599 599 48 21.50 600 600 48 21.15 601 CFA-R:601 Random: 602 602 proc time (s) 603 603 1 8.49 -
doc/theses/colby_parsons_MMAth/benchmarks/channels/plotData.py
ra50fdfb r6e1e2d0 70 70 if currBench == Bench.Unset: 71 71 if line == "contend:": 72 name = "C ontend"72 name = "Channel Contention" 73 73 currBench = Bench.Contend 74 74 elif line == "zero:": -
doc/theses/colby_parsons_MMAth/code/swap_queues.cfa
ra50fdfb r6e1e2d0 1 // this is a code stub and will not compile 2 3 // tries to atomically swap two queues and returns 0p if the swap failed 4 // returns ptr to newly owned queue if swap succeeds 5 static inline work_queue * try_swap_queues( worker & this, unsigned int victim_idx, unsigned int my_idx ) with(this) { 1 // sequential equivalent swap 2 void swap( uint victim_idx, uint my_idx ) { 3 // Step 0: 6 4 work_queue * my_queue = request_queues[my_idx]; 7 work_queue * other_queue = request_queues[victim_idx]; 8 9 // if either queue is 0p then they are in the process of being stolen 10 if ( other_queue == 0p || my_queue == 0p ) return 0p; 11 12 // try to set our queue ptr to be 0p. If it fails someone moved our queue so return false 13 if ( !__atomic_compare_exchange_n( &request_queues[my_idx], &my_queue, 0p, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) 14 return 0p; 15 16 // try to set other queue ptr to be our queue ptr. If it fails someone moved the other queue so fix up then return false 17 if ( !__atomic_compare_exchange_n( &request_queues[victim_idx], &other_queue, my_queue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ) ) { 18 /* paranoid */ verify( request_queues[my_idx] == 0p ); 19 request_queues[my_idx] = my_queue; // reset my queue ptr back to appropriate val 20 return 0p; 21 } 22 23 // we have successfully swapped and since our queue is 0p no one will touch it so write back new queue ptr non atomically 24 request_queues[my_idx] = other_queue; // last write does not need to be atomic 25 return other_queue; 5 work_queue * vic_queue = request_queues[victim_idx]; 6 // Step 2: 7 request_queues[my_idx] = 0p; 8 // Step 3: 9 request_queues[victim_idx] = my_queue; 10 // Step 4: 11 request_queues[my_idx] = vic_queue; 26 12 } 27 13 … … 35 21 36 22 bool try_swap_queues( worker & this, uint victim_idx, uint my_idx ) with(this) { 23 // Step 0: 24 // request_queues is the shared array of all sharded queues 37 25 work_queue * my_queue = request_queues[my_idx]; 38 26 work_queue * vic_queue = request_queues[victim_idx]; 39 27 28 // Step 1: 40 29 // If either queue is 0p then they are in the process of being stolen 41 30 // 0p is CForAll's equivalent of C++'s nullptr 42 if ( vic_queue == 0p || my_queue == 0p) return false;31 if ( vic_queue == 0p ) return false; 43 32 44 // Try to set our queue ptr to be 0p. 45 // If this CAS fails someone moved our queue so return false 33 // Step 2: 34 // Try to set thief's queue ptr to be 0p. 35 // If this CAS fails someone stole thief's queue so return false 46 36 if ( !CAS( &request_queues[my_idx], &my_queue, 0p ) ) 47 37 return false; 48 49 // Try to set other queue ptr to be our queue ptr. 50 // If it fails someone moved the other queue, so fix up then return false 38 39 // Step 3: 40 // Try to set victim queue ptr to be thief's queue ptr. 41 // If it fails someone stole the other queue, so fix up then return false 51 42 if ( !CAS( &request_queues[victim_idx], &vic_queue, my_queue ) ) { 52 43 request_queues[my_idx] = my_queue; // reset queue ptr back to prev val … … 54 45 } 55 46 47 // Step 4: 56 48 // Successfully swapped. 57 // Our queue is 0p so no one will touch it so write back without CAS is safe 49 // Thief's ptr is 0p so no one will touch it 50 // Write back without CAS is safe 58 51 request_queues[my_idx] = vic_queue; 59 52 return true; -
doc/theses/colby_parsons_MMAth/style/style.tex
ra50fdfb r6e1e2d0 3 3 \lstset{language=CFA} % default language 4 4 5 \newcommand{\newtermFont}{\emph} 6 \newcommand{\Newterm}[1]{\newtermFont{#1}} 7 5 8 \newcommand{\code}[1]{\lstinline[language=CFA]{#1}} 6 9 \newcommand{\uC}{$\mu$\CC} 10 \newcommand{\PAB}[1]{{\color{red}PAB: #1}} 7 11 12 \newsavebox{\myboxA} % used with subfigure 13 \newsavebox{\myboxB} 14 15 \lstnewenvironment{java}[1][] 16 {\lstset{language=java,moredelim=**[is][\protect\color{red}]{@}{@}}\lstset{#1}} 17 {} -
doc/theses/colby_parsons_MMAth/text/actors.tex
ra50fdfb r6e1e2d0 90 90 \begin{cfa} 91 91 struct derived_actor { 92 inline actor;// Plan-9 C inheritance92 inline actor; // Plan-9 C inheritance 93 93 }; 94 94 void ?{}( derived_actor & this ) { // Default ctor 95 95 ((actor &)this){}; // Call to actor ctor 96 96 } 97 97 98 98 struct derived_msg { 99 inline message;// Plan-9 C nominal inheritance100 99 inline message; // Plan-9 C nominal inheritance 100 char word[12]; 101 101 }; 102 102 void ?{}( derived_msg & this, char * new_word ) { // Overloaded ctor 103 104 103 ((message &) this){ Nodelete }; // Passing allocation to ctor 104 strcpy(this.word, new_word); 105 105 } 106 106 107 107 Allocation receive( derived_actor & receiver, derived_msg & msg ) { 108 109 108 printf("The message contained the string: %s\n", msg.word); 109 return Finished; // Return finished since actor is done 110 110 } 111 111 112 112 int main() { 113 114 derived_actor my_actor;115 116 117 118 113 start_actor_system(); // Sets up executor 114 derived_actor my_actor; 115 derived_msg my_msg{ "Hello World" }; // Constructor call 116 my_actor << my_msg; // Send message via left shift operator 117 stop_actor_system(); // Waits until actors are finished 118 return 0; 119 119 } 120 120 \end{cfa} … … 229 229 \section{Envelopes}\label{s:envelope} 230 230 In actor systems messages are sent and received by actors. 231 When a actor receives a message it 231 When a actor receives a message it executes its behaviour that is associated with that message type. 232 232 However the unit of work that stores the message, the receiving actor's address, and other pertinent information needs to persist between send and the receive. 233 233 Furthermore the unit of work needs to be able to be stored in some fashion, usually in a queue, until it is executed by an actor. … … 301 301 While other systems are concerned with stealing actors, the \CFA actor system steals queues. 302 302 This is a result of \CFA's use of the inverted actor system. 303 303 The goal of the \CFA actor work stealing mechanism is to have a zero-victim-cost stealing mechanism. 304 304 This does not means that stealing has no cost. 305 305 This goal is to ensure that stealing work does not impact the performance of victim workers. … … 369 369 370 370 \begin{cfa} 371 void swap( uint victim_idx, uint my_idx 372 373 374 375 376 377 378 379 380 371 void swap( uint victim_idx, uint my_idx ) { 372 // Step 0: 373 work_queue * my_queue = request_queues[my_idx]; 374 work_queue * vic_queue = request_queues[victim_idx]; 375 // Step 2: 376 request_queues[my_idx] = 0p; 377 // Step 3: 378 request_queues[victim_idx] = my_queue; 379 // Step 4: 380 request_queues[my_idx] = vic_queue; 381 381 } 382 382 \end{cfa} … … 389 389 // This routine is atomic 390 390 bool CAS( work_queue ** ptr, work_queue ** old, work_queue * new ) { 391 392 393 394 391 if ( *ptr != *old ) 392 return false; 393 *ptr = new; 394 return true; 395 395 } 396 396 397 397 bool try_swap_queues( worker & this, uint victim_idx, uint my_idx ) with(this) { 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 398 // Step 0: 399 // request_queues is the shared array of all sharded queues 400 work_queue * my_queue = request_queues[my_idx]; 401 work_queue * vic_queue = request_queues[victim_idx]; 402 403 // Step 1: 404 // If either queue is 0p then they are in the process of being stolen 405 // 0p is CForAll's equivalent of C++'s nullptr 406 if ( vic_queue == 0p ) return false; 407 408 // Step 2: 409 // Try to set thief's queue ptr to be 0p. 410 // If this CAS fails someone stole thief's queue so return false 411 if ( !CAS( &request_queues[my_idx], &my_queue, 0p ) ) 412 return false; 413 414 // Step 3: 415 // Try to set victim queue ptr to be thief's queue ptr. 416 // If it fails someone stole the other queue, so fix up then return false 417 if ( !CAS( &request_queues[victim_idx], &vic_queue, my_queue ) ) { 418 request_queues[my_idx] = my_queue; // reset queue ptr back to prev val 419 return false; 420 } 421 422 // Step 4: 423 // Successfully swapped. 424 // Thief's ptr is 0p so no one will touch it 425 // Write back without CAS is safe 426 request_queues[my_idx] = vic_queue; 427 return true; 428 428 } 429 429 \end{cfa}\label{c:swap} … … 706 706 \label{t:StaticActorMessagePerformance} 707 707 \begin{tabular}{*{5}{r|}r} 708 709 \hline 710 711 \hline 712 708 & \multicolumn{1}{c|}{\CFA (100M)} & \multicolumn{1}{c|}{CAF (10M)} & \multicolumn{1}{c|}{Akka (100M)} & \multicolumn{1}{c|}{\uC (100M)} & \multicolumn{1}{c@{}}{ProtoActor (100M)} \\ 709 \hline 710 AMD & \input{data/pykeSendStatic} \\ 711 \hline 712 Intel & \input{data/nasusSendStatic} 713 713 \end{tabular} 714 714 … … 719 719 720 720 \begin{tabular}{*{5}{r|}r} 721 722 \hline 723 724 \hline 725 721 & \multicolumn{1}{c|}{\CFA (20M)} & \multicolumn{1}{c|}{CAF (2M)} & \multicolumn{1}{c|}{Akka (2M)} & \multicolumn{1}{c|}{\uC (20M)} & \multicolumn{1}{c@{}}{ProtoActor (2M)} \\ 722 \hline 723 AMD & \input{data/pykeSendDynamic} \\ 724 \hline 725 Intel & \input{data/nasusSendDynamic} 726 726 \end{tabular} 727 727 \end{table} … … 745 745 In the static send benchmark all systems except CAF have static send costs that are in the same ballpark, only varying by ~70ns. 746 746 In the dynamic send benchmark all systems experience slower message sends, as expected due to the extra allocations. 747 However, 747 However, Akka and ProtoActor, slow down by a more significant margin than the \uC and \CFA. 748 748 This is likely a result of Akka and ProtoActor's garbage collection, which can suffer from hits in performance for allocation heavy workloads, whereas \uC and \CFA have explicit allocation/deallocation. 749 749 … … 753 753 754 754 \begin{figure} 755 \centering 756 \begin{subfigure}{0.5\textwidth} 757 \centering 758 \scalebox{0.5}{\input{figures/nasusCFABalance-One.pgf}} 759 \subcaption{AMD \CFA Balance-One Benchmark} 760 \label{f:BalanceOneAMD} 761 \end{subfigure}\hfill 762 \begin{subfigure}{0.5\textwidth} 763 \centering 764 \scalebox{0.5}{\input{figures/pykeCFABalance-One.pgf}} 765 \subcaption{Intel \CFA Balance-One Benchmark} 766 \label{f:BalanceOneIntel} 767 \end{subfigure} 768 \caption{The balance-one benchmark comparing stealing heuristics (lower is better).} 769 \end{figure} 770 771 \begin{figure} 772 \centering 773 \begin{subfigure}{0.5\textwidth} 774 \centering 775 \scalebox{0.5}{\input{figures/nasusCFABalance-Multi.pgf}} 776 \subcaption{AMD \CFA Balance-Multi Benchmark} 777 \label{f:BalanceMultiAMD} 778 \end{subfigure}\hfill 779 \begin{subfigure}{0.5\textwidth} 780 \centering 781 \scalebox{0.5}{\input{figures/pykeCFABalance-Multi.pgf}} 782 \subcaption{Intel \CFA Balance-Multi Benchmark} 783 \label{f:BalanceMultiIntel} 784 \end{subfigure} 785 \caption{The balance-multi benchmark comparing stealing heuristics (lower is better).} 755 \centering 756 \subfloat[AMD \CFA Balance-One Benchmark]{ 757 \resizebox{0.5\textwidth}{!}{\input{figures/nasusCFABalance-One.pgf}} 758 \label{f:BalanceOneAMD} 759 } 760 \subfloat[Intel \CFA Balance-One Benchmark]{ 761 \resizebox{0.5\textwidth}{!}{\input{figures/pykeCFABalance-One.pgf}} 762 \label{f:BalanceOneIntel} 763 } 764 \caption{The balance-one benchmark comparing stealing heuristics (lower is better).} 765 \end{figure} 766 767 \begin{figure} 768 \centering 769 \subfloat[AMD \CFA Balance-Multi Benchmark]{ 770 \resizebox{0.5\textwidth}{!}{\input{figures/nasusCFABalance-Multi.pgf}} 771 \label{f:BalanceMultiAMD} 772 } 773 \subfloat[Intel \CFA Balance-Multi Benchmark]{ 774 \resizebox{0.5\textwidth}{!}{\input{figures/pykeCFABalance-Multi.pgf}} 775 \label{f:BalanceMultiIntel} 776 } 777 \caption{The balance-multi benchmark comparing stealing heuristics (lower is better).} 786 778 \end{figure} 787 779 … … 817 809 818 810 \begin{figure} 819 \centering 820 \begin{subfigure}{0.5\textwidth} 821 \centering 822 \scalebox{0.5}{\input{figures/nasusExecutor.pgf}} 823 \subcaption{AMD Executor Benchmark} 824 \label{f:ExecutorAMD} 825 \end{subfigure}\hfill 826 \begin{subfigure}{0.5\textwidth} 827 \centering 828 \scalebox{0.5}{\input{figures/pykeExecutor.pgf}} 829 \subcaption{Intel Executor Benchmark} 830 \label{f:ExecutorIntel} 831 \end{subfigure} 832 \caption{The executor benchmark comparing actor systems (lower is better).} 811 \centering 812 \subfloat[AMD Executor Benchmark]{ 813 \resizebox{0.5\textwidth}{!}{\input{figures/nasusExecutor.pgf}} 814 \label{f:ExecutorAMD} 815 } 816 \subfloat[Intel Executor Benchmark]{ 817 \resizebox{0.5\textwidth}{!}{\input{figures/pykeExecutor.pgf}} 818 \label{f:ExecutorIntel} 819 } 820 \caption{The executor benchmark comparing actor systems (lower is better).} 833 821 \end{figure} 834 822 … … 840 828 841 829 \begin{figure} 842 \centering 843 \begin{subfigure}{0.5\textwidth} 844 \centering 845 \scalebox{0.5}{\input{figures/nasusCFAExecutor.pgf}} 846 \subcaption{AMD \CFA Executor Benchmark}\label{f:cfaExecutorAMD} 847 \end{subfigure}\hfill 848 \begin{subfigure}{0.5\textwidth} 849 \centering 850 \scalebox{0.5}{\input{figures/pykeCFAExecutor.pgf}} 851 \subcaption{Intel \CFA Executor Benchmark}\label{f:cfaExecutorIntel} 852 \end{subfigure} 853 \caption{Executor benchmark comparing \CFA stealing heuristics (lower is better).} 830 \centering 831 \subfloat[AMD \CFA Executor Benchmark]{ 832 \resizebox{0.5\textwidth}{!}{\input{figures/nasusCFAExecutor.pgf}} 833 \label{f:cfaExecutorAMD} 834 } 835 \subfloat[Intel \CFA Executor Benchmark]{ 836 \resizebox{0.5\textwidth}{!}{\input{figures/pykeCFAExecutor.pgf}} 837 \label{f:cfaExecutorIntel} 838 } 839 \caption{Executor benchmark comparing \CFA stealing heuristics (lower is better).} 854 840 \end{figure} 855 841 … … 857 843 858 844 \begin{figure} 859 \centering 860 \begin{subfigure}{0.5\textwidth} 861 \centering 862 \scalebox{0.5}{\input{figures/nasusRepeat.pgf}} 863 \subcaption{AMD Repeat Benchmark}\label{f:RepeatAMD} 864 \end{subfigure}\hfill 865 \begin{subfigure}{0.5\textwidth} 866 \centering 867 \scalebox{0.5}{\input{figures/pykeRepeat.pgf}} 868 \subcaption{Intel Repeat Benchmark}\label{f:RepeatIntel} 869 \end{subfigure} 870 \caption{The repeat benchmark comparing actor systems (lower is better).} 845 \centering 846 \subfloat[AMD Repeat Benchmark]{ 847 \resizebox{0.5\textwidth}{!}{\input{figures/nasusRepeat.pgf}} 848 \label{f:RepeatAMD} 849 } 850 \subfloat[Intel Repeat Benchmark]{ 851 \resizebox{0.5\textwidth}{!}{\input{figures/pykeRepeat.pgf}} 852 \label{f:RepeatIntel} 853 } 854 \caption{The repeat benchmark comparing actor systems (lower is better).} 871 855 \end{figure} 872 856 … … 881 865 882 866 \begin{figure} 883 \centering 884 \begin{subfigure}{0.5\textwidth} 885 \centering 886 \scalebox{0.5}{\input{figures/nasusCFARepeat.pgf}} 887 \subcaption{AMD \CFA Repeat Benchmark}\label{f:cfaRepeatAMD} 888 \end{subfigure}\hfill 889 \begin{subfigure}{0.5\textwidth} 890 \centering 891 \scalebox{0.5}{\input{figures/pykeCFARepeat.pgf}} 892 \subcaption{Intel \CFA Repeat Benchmark}\label{f:cfaRepeatIntel} 893 \end{subfigure} 894 \caption{The repeat benchmark comparing \CFA stealing heuristics (lower is better).} 867 \centering 868 \subfloat[AMD \CFA Repeat Benchmark]{ 869 \resizebox{0.5\textwidth}{!}{\input{figures/nasusCFARepeat.pgf}} 870 \label{f:cfaRepeatAMD} 871 } 872 \subfloat[Intel \CFA Repeat Benchmark]{ 873 \resizebox{0.5\textwidth}{!}{\input{figures/pykeCFARepeat.pgf}} 874 \label{f:cfaRepeatIntel} 875 } 876 \caption{The repeat benchmark comparing \CFA stealing heuristics (lower is better).} 895 877 \end{figure} 896 878 … … 913 895 914 896 \begin{table}[t] 915 916 917 918 919 920 921 922 923 \hline 924 925 \hline 926 927 897 \centering 898 \setlength{\extrarowheight}{2pt} 899 \setlength{\tabcolsep}{5pt} 900 901 \caption{Executor Program Memory High Watermark} 902 \label{t:ExecutorMemory} 903 \begin{tabular}{*{5}{r|}r} 904 & \multicolumn{1}{c|}{\CFA} & \multicolumn{1}{c|}{CAF} & \multicolumn{1}{c|}{Akka} & \multicolumn{1}{c|}{\uC} & \multicolumn{1}{c@{}}{ProtoActor} \\ 905 \hline 906 AMD & \input{data/pykeExecutorMem} \\ 907 \hline 908 Intel & \input{data/nasusExecutorMem} 909 \end{tabular} 928 910 \end{table} 929 911 … … 951 933 952 934 \begin{figure} 953 954 \begin{subfigure}{0.5\textwidth} 955 \centering 956 \scalebox{0.5}{\input{figures/nasusMatrix.pgf}}957 \subcaption{AMD Matrix Benchmark}\label{f:MatrixAMD}958 \end{subfigure}\hfill 959 \begin{subfigure}{0.5\textwidth}960 \centering 961 \scalebox{0.5}{\input{figures/pykeMatrix.pgf}}962 \subcaption{Intel Matrix Benchmark}\label{f:MatrixIntel}963 \end{subfigure}964 \caption{The matrix benchmark comparing actor systems (lower is better).} 965 \ end{figure}966 967 \begin{figure} 968 \centering 969 \begin{subfigure}{0.5\textwidth}970 \centering 971 \scalebox{0.5}{\input{figures/nasusCFAMatrix.pgf}} 972 \subcaption{AMD \CFA Matrix Benchmark}\label{f:cfaMatrixAMD}973 \end{subfigure}\hfill 974 \begin{subfigure}{0.5\textwidth}975 \centering 976 \scalebox{0.5}{\input{figures/pykeCFAMatrix.pgf}}977 \subcaption{Intel \CFA Matrix Benchmark}\label{f:cfaMatrixIntel} 978 \end{subfigure} 979 \caption{The matrix benchmark comparing \CFA stealing heuristics (lower is better).} 980 \end{figure} 935 \centering 936 \subfloat[AMD Matrix Benchmark]{ 937 \resizebox{0.5\textwidth}{!}{\input{figures/nasusMatrix.pgf}} 938 \label{f:MatrixAMD} 939 } 940 \subfloat[Intel Matrix Benchmark]{ 941 \resizebox{0.5\textwidth}{!}{\input{figures/pykeMatrix.pgf}} 942 \label{f:MatrixIntel} 943 } 944 \caption{The matrix benchmark comparing actor systems (lower is better).} 945 \end{figure} 946 947 \begin{figure} 948 \centering 949 \subfloat[AMD \CFA Matrix Benchmark]{ 950 \resizebox{0.5\textwidth}{!}{\input{figures/nasusCFAMatrix.pgf}} 951 \label{f:cfaMatrixAMD} 952 } 953 \subfloat[Intel \CFA Matrix Benchmark]{ 954 \resizebox{0.5\textwidth}{!}{\input{figures/pykeCFAMatrix.pgf}} 955 \label{f:cfaMatrixIntel} 956 } 957 \caption{The matrix benchmark comparing \CFA stealing heuristics (lower is better).} 958 \end{figure} 959 960 % Local Variables: % 961 % tab-width: 4 % 962 % End: % -
doc/theses/colby_parsons_MMAth/text/channels.tex
ra50fdfb r6e1e2d0 5 5 % ====================================================================== 6 6 7 Channels were first introduced by Hoare in his paper Communicating Sequentual Processes~\cite{Hoare78}, where he proposes a concurrent language that communicates across processes using input/output channels to send data. 8 Channels are a concurrent language feature used to perform message passing concurrency, a model of concurrency where threads communicate by sending data as messages, and synchronizing via the message passing mechanism. 9 This is an alternative to shared memory concurrency, where threads can communicate directly by changing shared memory state. 10 Most modern concurrent programming languages do not subscribe to just one style of communication between threads, and provide features that support both. 7 Channels are a concurrent-language feature used to perform \Newterm{message-passing concurrency}: a model of concurrency where threads communicate by sending (mostly nonblocking) data as messages and synchronizing by receiving (blocking) sent data. 8 This model is an alternative to shared-memory concurrency, where threads can communicate directly by changing shared state. 9 Most modern concurrent programming languages do not subscribe to just one style of communication among threads and provide features that support multiple approaches. 10 11 Channels were first introduced by Kahn~\cite{Kahn74} and extended by Hoare~\cite{Hoare78} (CSP). 12 Both papers present a pseudo (unimplemented) concurrent language where processes communicate using input/output channels to send data. 13 Both languages are highly restrictive. 14 Kahn's language restricts a reading process to only wait for data on a single channel at a time and different writing processes cannot send data on the same channel. 15 Hoare's language restricts ... 11 16 Channels as a programming language feature has been popularized in recent years due to the language Go, which encourages the use of channels as its fundamental concurrent feature. 17 Go's restrictions are ... 18 \CFA channels do not have these restrictions. 12 19 13 20 \section{Producer-Consumer Problem} 14 Most channels in modern programming languages are built on top of a shared memory buffer. 15 While it is possible to create a channel that contains an unbounded buffer, most implementations opt to only support a fixed size channel, where the size is given at the time of channel creation. 16 This turns the implementation of a channel into the producer-consumer problem. 17 The producer-consumer problem, also known as the bounded buffer problem, was introduced by Dijkstra in his book Cooperating Sequential Processes\cite{Dijkstra65}. 18 In the problem threads interact with the buffer in two ways, either consuming values by removing them from the buffer, or producing values and inserting them in the buffer. 19 The buffer needs to be protected from concurrent access since each item in the buffer should only be produced and consumed once. 21 Most channels in modern programming languages are built on top of a shared memory buffer. 22 While it is possible to create a channel that contains an unbounded buffer, most implementations opt to only support a fixed size channel, where the size is given at the time of channel creation. 23 This turns the implementation of a channel into the producer-consumer problem. 24 The producer-consumer problem, also known as the bounded buffer problem, was introduced by Dijkstra in his book Cooperating Sequential Processes\cite{Dijkstra65}. 25 In the problem threads interact with the buffer in two ways, either consuming values by removing them from the buffer, or producing values and inserting them in the buffer. 26 The buffer needs to be protected from concurrent access since each item in the buffer should only be produced and consumed once. 20 27 Additionally, a consumer can only remove from a non-empty buffer and a producer can only insert into a non-full buffer. 21 28 22 29 \section{First-Come First-Served} 23 The channel implementations that will be discussed are \gls{fcfs}. 24 This term was defined by Lamport~\cite{Lamport74}. 25 \gls{fcfs} is defined in relation to a doorway~\cite[p.~330]{Lamport86II}, which is the point at which an ordering among threads can be established. 26 Given this doorway, a critical section is said to be \gls{fcfs}, if threads access the shared resource in the order they proceed through the doorway. 27 \gls{fcfs} is a fairness property which prevents unequal access to the shared resource and prevents starvation, however it can come at a cost. 28 Implementing an algorithm with \gls{fcfs} can lead to double blocking, where entering threads may need to block to allow other threads to proceed first, resulting in blocking both inside and outside the doorway. 30 The channel implementations that will be discussed are \gls{fcfs}. 31 This term was defined by Lamport~\cite{Lamport74}. 32 \gls{fcfs} is defined in relation to a doorway~\cite[p.~330]{Lamport86II}, which is the point at which an ordering among threads can be established. 33 Given this doorway, a critical section is said to be \gls{fcfs}, if threads access the shared resource in the order they proceed through the doorway. 34 \gls{fcfs} is a fairness property which prevents unequal access to the shared resource and prevents starvation, however it can come at a cost. 35 Implementing an algorithm with \gls{fcfs} can lead to double blocking, where entering threads may need to block to allow other threads to proceed first, resulting in blocking both inside and outside the doorway. 29 36 As such algorithms that are not \gls{fcfs} may be more performant but that performance comes with the downside of likely introducing starvation and unfairness. 30 37 31 38 \section{Channel Implementation} 32 The channel implementation in \CFA is a near carbon copy of the Go implementation. 33 Experimentation was conducted that varied the producer-consumer problem algorithm and lock type used inside the channel. 34 With the exception of non-\gls{fcfs} algorithms, no algorithm or lock usage in the channel implementation was found to be consistently more performant that Go's choice of algorithm and lock implementation. 39 The channel implementation in \CFA is a near carbon copy of the Go implementation. 40 Experimentation was conducted that varied the producer-consumer problem algorithm and lock type used inside the channel. 41 With the exception of non-\gls{fcfs} algorithms, no algorithm or lock usage in the channel implementation was found to be consistently more performant that Go's choice of algorithm and lock implementation. 35 42 As such the research contributions added by \CFA's channel implementation lie in the realm of safety and productivity features. 36 43 37 44 \section{Safety and Productivity} 38 Channels in \CFA come with safety and productivity features to aid users. 45 Channels in \CFA come with safety and productivity features to aid users. 39 46 The features include the following. 40 47 41 48 \begin{itemize} 42 \item Toggle-able statistic collection on channel beh vaiour that counts channel operations, and the number of the operations that block.49 \item Toggle-able statistic collection on channel behaviour that counts channel operations, and the number of the operations that block. 43 50 Tracking blocking operations helps users tune their channel size or channel usage when the channel is used for buffering, where the aim is to have as few blocking operations as possible. 44 \item Deadlock detection on deallocation of the channel. 51 \item Deadlock detection on deallocation of the channel. 45 52 If any threads are blocked inside the channel when it terminates it is detected and informs the user, as this would cause a deadlock. 46 \item A \code{flush} routine that delivers copies of an element to all waiting consumers, flushing the buffer. 47 Programmers can use this to easily to broadcast data to multiple consumers. 48 Additionally, the \code{flush} routine is more performant then looping around the \code{insert} operation since it can deliver the elements without having to rea quire mutual exclusion for each element sent.53 \item A \code{flush} routine that delivers copies of an element to all waiting consumers, flushing the buffer. 54 Programmers can use this to easily to broadcast data to multiple consumers. 55 Additionally, the \code{flush} routine is more performant then looping around the \code{insert} operation since it can deliver the elements without having to reacquire mutual exclusion for each element sent. 49 56 \end{itemize} 50 57 51 The other safety and productivity feature of \CFA channels deals with concurrent termination. 52 Terminating concurrent programs is often one of the most difficult parts of writing concurrent code, particularly if graceful termination is needed. 53 The difficulty of graceful termination often arises from the usage of synchronization primitives which need to be handled carefully during shutdown. 54 It is easy to deadlock during termination if threads are left behind on synchronization primitives. 55 Additionally, most synchronization primitives are prone to \gls{toctou} issues where there is race between one thread checking the state of a concurrent object and another thread changing the state. 56 \gls{toctou} issues with synchronization primitives often involve a race between one thread checking the primitive for blocked threads and another thread blocking on it. 57 Channels are a particularly hard synchronization primitive to terminate since both sending and receiving off a channel can block. 58 The other safety and productivity feature of \CFA channels deals with concurrent termination. 59 Terminating concurrent programs is often one of the most difficult parts of writing concurrent code, particularly if graceful termination is needed. 60 The difficulty of graceful termination often arises from the usage of synchronization primitives which need to be handled carefully during shutdown. 61 It is easy to deadlock during termination if threads are left behind on synchronization primitives. 62 Additionally, most synchronization primitives are prone to \gls{toctou} issues where there is race between one thread checking the state of a concurrent object and another thread changing the state. 63 \gls{toctou} issues with synchronization primitives often involve a race between one thread checking the primitive for blocked threads and another thread blocking on it. 64 Channels are a particularly hard synchronization primitive to terminate since both sending and receiving off a channel can block. 58 65 Thus, improperly handled \gls{toctou} issues with channels often result in deadlocks as threads trying to perform the termination may end up unexpectedly blocking in their attempt to help other threads exit the system. 59 66 60 67 % C_TODO: add reference to select chapter, add citation to go channels info 61 Go channels provide a set of tools to help with concurrent shutdown. 62 Channels in Go have a \code{close} operation and a \code{select} statement that both can be used to help threads terminate. 63 The \code{select} statement will be discussed in \ref{}, where \CFA's \code{waituntil} statement will be compared with the Go \code{select} statement. 64 The \code{close} operation on a channel in Go changes the state of the channel. 65 When a channel is closed, sends to the channel will panic and additional calls to \code{close} will panic. 66 Receives are handled differently where receivers will never block on a closed channel and will continue to remove elements from the channel. 67 Once a channel is empty, receivers can continue to remove elements, but will receive the zero-value version of the element type. 68 To aid in avoiding unwanted zero-value elements, Go provides the ability to iterate over a closed channel to remove the remaining elements. 69 These design choices for Go channels enforce a specific interaction style with channels during termination, where careful thought is needed to ensure that additional \code{close} calls don't occur and that no sends occur after channels are closed. 70 These design choices fit Go's paradigm of error management, where users are expected to explicitly check for errors, rather than letting errors occur and catching them. 71 If errors need to occur in Go, return codes are used to pass error information where they are needed. 68 Go channels provide a set of tools to help with concurrent shutdown. 69 Channels in Go have a \code{close} operation and a \code{select} statement that both can be used to help threads terminate. 70 The \code{select} statement will be discussed in \ref{}, where \CFA's \code{waituntil} statement will be compared with the Go \code{select} statement. 71 The \code{close} operation on a channel in Go changes the state of the channel. 72 When a channel is closed, sends to the channel will panic and additional calls to \code{close} will panic. 73 Receives are handled differently where receivers will never block on a closed channel and will continue to remove elements from the channel. 74 Once a channel is empty, receivers can continue to remove elements, but will receive the zero-value version of the element type. 75 To aid in avoiding unwanted zero-value elements, Go provides the ability to iterate over a closed channel to remove the remaining elements. 76 These design choices for Go channels enforce a specific interaction style with channels during termination, where careful thought is needed to ensure that additional \code{close} calls don't occur and that no sends occur after channels are closed. 77 These design choices fit Go's paradigm of error management, where users are expected to explicitly check for errors, rather than letting errors occur and catching them. 78 If errors need to occur in Go, return codes are used to pass error information where they are needed. 72 79 Note that panics in Go can be caught, but it is not considered an idiomatic way to write Go programs. 73 80 74 While Go's channel closing semantics are powerful enough to perform any concurrent termination needed by a program, their lack of ease of use leaves much to be desired. 75 Since both closing and sending panic, once a channel is closed, a user often has to synchronize the senders to a channel before the channel can be closed to avoid panics. 76 However, in doing so it renders the \code{close} operation nearly useless, as the only utilities it provides are the ability to ensure that receivers no longer block on the channel, and will receive zero-valued elements. 77 This can be useful if the zero-typed element is recognized as a sentinel value, but if another sentinel value is preferred, then \code{close} only provides its non-blocking feature. 78 To avoid \gls{toctou} issues during shutdown, a busy wait with a \code{select} statement is often used to add or remove elements from a channel. 81 While Go's channel closing semantics are powerful enough to perform any concurrent termination needed by a program, their lack of ease of use leaves much to be desired. 82 Since both closing and sending panic, once a channel is closed, a user often has to synchronize the senders to a channel before the channel can be closed to avoid panics. 83 However, in doing so it renders the \code{close} operation nearly useless, as the only utilities it provides are the ability to ensure that receivers no longer block on the channel, and will receive zero-valued elements. 84 This can be useful if the zero-typed element is recognized as a sentinel value, but if another sentinel value is preferred, then \code{close} only provides its non-blocking feature. 85 To avoid \gls{toctou} issues during shutdown, a busy wait with a \code{select} statement is often used to add or remove elements from a channel. 79 86 Due to Go's asymmetric approach to channel shutdown, separate synchronization between producers and consumers of a channel has to occur during shutdown. 80 87 … … 82 89 As such \CFA uses an exception based approach to channel shutdown that is symmetric for both producers and consumers, and supports graceful shutdown.Exceptions in \CFA support both termination and resumption.Termination exceptions operate in the same way as exceptions seen in many popular programming languages such as \CC, Python and Java. 83 90 Resumption exceptions are a style of exception that when caught run the corresponding catch block in the same way that termination exceptions do. 84 The difference between the exception handling mechanisms arises after the exception is handled. 85 In termination handling, the control flow continues into the code following the catch after the exception is handled. 86 In resumption handling, the control flow returns to the site of the \code{throw}, allowing the control to continue where it left off. 87 Note that in resumption, since control can return to the point of error propagation, the stack is not unwound during resumption propagation. 88 In \CFA if a resumption is not handled, it is reraised as a termination. 91 The difference between the exception handling mechanisms arises after the exception is handled. 92 In termination handling, the control flow continues into the code following the catch after the exception is handled. 93 In resumption handling, the control flow returns to the site of the \code{throw}, allowing the control to continue where it left off. 94 Note that in resumption, since control can return to the point of error propagation, the stack is not unwound during resumption propagation. 95 In \CFA if a resumption is not handled, it is reraised as a termination. 89 96 This mechanism can be used to create a flexible and robust termination system for channels. 90 97 91 When a channel in \CFA is closed, all subsequent calls to the channel will throw a resumption exception at the caller. 92 If the resumption is handled, then the caller will proceed to attempt to complete their operation. 93 If the resumption is not handled it is then rethrown as a termination exception. 94 Or, if the resumption is handled, but the subsequent attempt at an operation would block, a termination exception is thrown. 95 These termination exceptions allow for non-local transfer that can be used to great effect to eagerly and gracefully shut down a thread. 96 When a channel is closed, if there are any blocked producers or consumers inside the channel, they are woken up and also have a resumption thrown at them. 97 The resumption exception, \code{channel_closed}, has a couple fields to aid in handling the exception. 98 The exception contains a pointer to the channel it was thrown from, and a pointer to an element. 99 In exceptions thrown from remove the element pointer will be null. 100 In the case of insert the element pointer points to the element that the thread attempted to insert. 101 This element pointer allows the handler to know which operation failed and also allows the element to not be lost on a failed insert since it can be moved elsewhere in the handler. 102 Furthermore, due to \CFA's powerful exception system, this data can be used to choose handlers based which channel and operation failed. 103 Exception handlers in \CFA have an optional predicate after the exception type which can be used to optionally trigger or skip handlers based on the content of an exception. 104 It is worth mentioning that the approach of exceptions for termination may incur a larger performance cost during termination that the approach used in Go. 98 When a channel in \CFA is closed, all subsequent calls to the channel will throw a resumption exception at the caller. 99 If the resumption is handled, then the caller will proceed to attempt to complete their operation. 100 If the resumption is not handled it is then rethrown as a termination exception. 101 Or, if the resumption is handled, but the subsequent attempt at an operation would block, a termination exception is thrown. 102 These termination exceptions allow for non-local transfer that can be used to great effect to eagerly and gracefully shut down a thread. 103 When a channel is closed, if there are any blocked producers or consumers inside the channel, they are woken up and also have a resumption thrown at them. 104 The resumption exception, \code{channel_closed}, has a couple fields to aid in handling the exception. 105 The exception contains a pointer to the channel it was thrown from, and a pointer to an element. 106 In exceptions thrown from remove the element pointer will be null. 107 In the case of insert the element pointer points to the element that the thread attempted to insert. 108 This element pointer allows the handler to know which operation failed and also allows the element to not be lost on a failed insert since it can be moved elsewhere in the handler. 109 Furthermore, due to \CFA's powerful exception system, this data can be used to choose handlers based which channel and operation failed. 110 Exception handlers in \CFA have an optional predicate after the exception type which can be used to optionally trigger or skip handlers based on the content of an exception. 111 It is worth mentioning that the approach of exceptions for termination may incur a larger performance cost during termination that the approach used in Go. 105 112 This should not be an issue, since termination is rarely an fast-path of an application and ensuring that termination can be implemented correctly with ease is the aim of the exception approach. 106 113 107 To highlight the differences between \CFA's and Go's close semantics, an example program is presented. 108 The program is a barrier implemented using two channels shown in Listings~\ref{l:cfa_chan_bar} and \ref{l:go_chan_bar}. 109 Both of these exa ples are implmented using \CFA syntax so that they can be easily compared.110 Listing~\ref{l:go_chan_bar} uses go-style channel close semantics and Listing~\ref{l:cfa_chan_bar} uses \CFA close semantics. 111 In this problem it is infeasible to use the Go \code{close} call since all tasks are both potentially producers and consumers, causing panics on close to be unavoidable. 112 As such in Listing~\ref{l:go_chan_bar} to implement a flush routine for the buffer, a sentinel value of $-1$ has to be used to indicate to threads that they need to leave the barrier. 113 This sentinel value has to be checked at two points. 114 Furthermore, an additional flag \code{done} is needed to communicate to threads once they have left the barrier that they are done. 115 This use of an additional flag or communication method is common in Go channel shutdown code, since to avoid panics on a channel, the shutdown of a channel often has to be communicated with threads before it occurs. 116 In the \CFA version~\ref{l:cfa_chan_bar}, the barrier shutdown results in an exception being thrown at threads operating on it, which informs the threads that they must terminate. 117 This avoids the need to use a separate communication method other than the barrier, and avoids extra conditional checks on the fast path of the barrier implementation. 114 To highlight the differences between \CFA's and Go's close semantics, an example program is presented. 115 The program is a barrier implemented using two channels shown in Listings~\ref{l:cfa_chan_bar} and \ref{l:go_chan_bar}. 116 Both of these examples are implemented using \CFA syntax so that they can be easily compared. 117 Listing~\ref{l:go_chan_bar} uses go-style channel close semantics and Listing~\ref{l:cfa_chan_bar} uses \CFA close semantics. 118 In this problem it is infeasible to use the Go \code{close} call since all tasks are both potentially producers and consumers, causing panics on close to be unavoidable. 119 As such in Listing~\ref{l:go_chan_bar} to implement a flush routine for the buffer, a sentinel value of $-1$ has to be used to indicate to threads that they need to leave the barrier. 120 This sentinel value has to be checked at two points. 121 Furthermore, an additional flag \code{done} is needed to communicate to threads once they have left the barrier that they are done. 122 This use of an additional flag or communication method is common in Go channel shutdown code, since to avoid panics on a channel, the shutdown of a channel often has to be communicated with threads before it occurs. 123 In the \CFA version~\ref{l:cfa_chan_bar}, the barrier shutdown results in an exception being thrown at threads operating on it, which informs the threads that they must terminate. 124 This avoids the need to use a separate communication method other than the barrier, and avoids extra conditional checks on the fast path of the barrier implementation. 118 125 Also note that in the Go version~\ref{l:go_chan_bar}, the size of the barrier channels has to be larger than in the \CFA version to ensure that the main thread does not block when attempting to clear the barrier. 119 126 120 \begin{cfa}[ tabsize=3,caption={\CFA channel barrier termination},label={l:cfa_chan_bar}]127 \begin{cfa}[caption={\CFA channel barrier termination},label={l:cfa_chan_bar}] 121 128 struct barrier { 122 123 124 129 channel( int ) barWait; 130 channel( int ) entryWait; 131 int size; 125 132 } 126 133 void ?{}(barrier & this, int size) with(this) { 127 128 129 130 131 134 barWait{size}; 135 entryWait{size}; 136 this.size = size; 137 for ( j; size ) 138 insert( *entryWait, j ); 132 139 } 133 140 134 141 void flush(barrier & this) with(this) { 135 136 142 close(barWait); 143 close(entryWait); 137 144 } 138 145 void wait(barrier & this) with(this) { 139 140 141 142 143 144 145 146 147 148 149 150 151 146 int ticket = remove( *entryWait ); 147 if ( ticket == size - 1 ) { 148 for ( j; size - 1 ) 149 insert( *barWait, j ); 150 return; 151 } 152 ticket = remove( *barWait ); 153 154 // last one out 155 if ( size == 1 || ticket == size - 2 ) { 156 for ( j; size ) 157 insert( *entryWait, j ); 158 } 152 159 } 153 160 barrier b{Tasks}; … … 155 162 // thread main 156 163 void main(Task & this) { 157 158 159 160 161 164 try { 165 for ( ;; ) { 166 wait( b ); 167 } 168 } catch ( channel_closed * e ) {} 162 169 } 163 170 164 171 int main() { 165 166 167 168 169 170 171 172 { 173 Task t[Tasks]; 174 175 sleep(10`s); 176 flush( b ); 177 } // wait for tasks to terminate 178 return 0; 172 179 } 173 180 \end{cfa} 174 181 175 \begin{cfa}[ tabsize=3,caption={Go channel barrier termination},label={l:go_chan_bar}]182 \begin{cfa}[caption={Go channel barrier termination},label={l:go_chan_bar}] 176 183 177 184 struct barrier { 178 179 180 185 channel( int ) barWait; 186 channel( int ) entryWait; 187 int size; 181 188 } 182 189 void ?{}(barrier & this, int size) with(this) { 183 184 185 186 187 190 barWait{size + 1}; 191 entryWait{size + 1}; 192 this.size = size; 193 for ( j; size ) 194 insert( *entryWait, j ); 188 195 } 189 196 190 197 void flush(barrier & this) with(this) { 191 192 198 insert( *entryWait, -1 ); 199 insert( *barWait, -1 ); 193 200 } 194 201 void wait(barrier & this) with(this) { 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 202 int ticket = remove( *entryWait ); 203 if ( ticket == -1 ) { 204 insert( *entryWait, -1 ); 205 return; 206 } 207 if ( ticket == size - 1 ) { 208 for ( j; size - 1 ) 209 insert( *barWait, j ); 210 return; 211 } 212 ticket = remove( *barWait ); 213 if ( ticket == -1 ) { 214 insert( *barWait, -1 ); 215 return; 216 } 217 218 // last one out 219 if ( size == 1 || ticket == size - 2 ) { 220 for ( j; size ) 221 insert( *entryWait, j ); 222 } 216 223 } 217 224 barrier b; … … 220 227 // thread main 221 228 void main(Task & this) { 222 223 224 225 229 for ( ;; ) { 230 if ( done ) break; 231 wait( b ); 232 } 226 233 } 227 234 228 235 int main() { 229 230 231 232 233 234 235 236 237 236 { 237 Task t[Tasks]; 238 239 sleep(10`s); 240 done = true; 241 242 flush( b ); 243 } // wait for tasks to terminate 244 return 0; 238 245 } 239 246 \end{cfa} 240 247 241 In Listing~\ref{l:cfa_resume} an example of channel closing with resumption is used. 242 This program uses resumption in the \code{Consumer} thread main to ensure that all elements in the channel are removed before the consumer thread terminates. 243 The producer only has a \code{catch} so the moment it receives an exception it terminates, whereas the consumer will continue to remove from the closed channel via handling resumptions until the buffer is empty, which then throws a termination exception. 248 In Listing~\ref{l:cfa_resume} an example of channel closing with resumption is used. 249 This program uses resumption in the \code{Consumer} thread main to ensure that all elements in the channel are removed before the consumer thread terminates. 250 The producer only has a \code{catch} so the moment it receives an exception it terminates, whereas the consumer will continue to remove from the closed channel via handling resumptions until the buffer is empty, which then throws a termination exception. 244 251 If the same program was implemented in Go it would require explicit synchronization with both producers and consumers by some mechanism outside the channel to ensure that all elements were removed before task termination. 245 252 246 \begin{cfa}[ tabsize=3,caption={\CFA channel resumption usage},label={l:cfa_resume}]253 \begin{cfa}[caption={\CFA channel resumption usage},label={l:cfa_resume}] 247 254 channel( int ) chan{ 128 }; 248 255 249 256 // Consumer thread main 250 257 void main(Consumer & this) { 251 252 253 254 255 256 257 catch ( channel_closed * e ) {} 258 size_t runs = 0; 259 try { 260 for ( ;; ) { 261 remove( chan ); 262 } 263 } catchResume ( channel_closed * e ) {} 264 catch ( channel_closed * e ) {} 258 265 } 259 266 260 267 // Producer thread main 261 268 void main(Producer & this) { 262 263 264 265 266 267 } catch ( channel_closed * e ) {} 269 int j = 0; 270 try { 271 for ( ;;j++ ) { 272 insert( chan, j ); 273 } 274 } catch ( channel_closed * e ) {} 268 275 } 269 276 270 277 int main( int argc, char * argv[] ) { 271 272 273 274 275 276 277 278 279 280 278 { 279 Consumers c[4]; 280 Producer p[4]; 281 282 sleep(10`s); 283 284 for ( i; Channels ) 285 close( channels[i] ); 286 } 287 return 0; 281 288 } 282 289 \end{cfa} … … 284 291 \section{Performance} 285 292 286 Given that the base implementation of the \CFA channels is very similar to the Go implementation, this section aims to show that the performance of the two implementations are comparable. 287 One microbenchmark is conducted to compare Go and \CFA. 288 The benchmark is a ten second experiment where producers and consumers operate on a channel in parallel and throughput is measured. 289 The number of cores is varied to measure how through tput scales.290 The cores are divided equally between producers and consumers, with one producer or consumer owning each core. 291 The results of the benchmark are shown in Figure~\ref{f:chanPerf}. 292 The performance of Go and \CFA channels on this microbenchmark is comparable. 293 Given that the base implementation of the \CFA channels is very similar to the Go implementation, this section aims to show that the performance of the two implementations are comparable. 294 One microbenchmark is conducted to compare Go and \CFA. 295 The benchmark is a ten second experiment where producers and consumers operate on a channel in parallel and throughput is measured. 296 The number of cores is varied to measure how throughput scales. 297 The cores are divided equally between producers and consumers, with one producer or consumer owning each core. 298 The results of the benchmark are shown in Figure~\ref{f:chanPerf}. 299 The performance of Go and \CFA channels on this microbenchmark is comparable. 293 300 Note, it is expected for the performance to decline as the number of cores increases as the channel operations all occur in a critical section so an increase in cores results in higher contention with no increase in parallelism. 294 301 295 302 296 303 \begin{figure} 297 \centering 298 \begin{subfigure}{0.5\textwidth} 299 \centering 300 \scalebox{0.5}{\input{figures/nasus_Channel_Contention.pgf}} 301 \subcaption{AMD \CFA Channel Benchmark}\label{f:chanAMD} 302 \end{subfigure}\hfill 303 \begin{subfigure}{0.5\textwidth} 304 \centering 305 \scalebox{0.5}{\input{figures/pyke_Channel_Contention.pgf}} 306 \subcaption{Intel \CFA Channel Benchmark}\label{f:chanIntel} 307 \end{subfigure} 308 \caption{The channel contention benchmark comparing \CFA and Go channel throughput (higher is better).} 309 \label{f:chanPerf} 304 \centering 305 \subfloat[AMD \CFA Channel Benchmark]{ 306 \resizebox{0.5\textwidth}{!}{\input{figures/nasus_Channel_Contention.pgf}} 307 \label{f:chanAMD} 308 } 309 \subfloat[Intel \CFA Channel Benchmark]{ 310 \resizebox{0.5\textwidth}{!}{\input{figures/pyke_Channel_Contention.pgf}} 311 \label{f:chanIntel} 312 } 313 \caption{The channel contention benchmark comparing \CFA and Go channel throughput (higher is better).} 314 \label{f:chanPerf} 310 315 \end{figure} 316 317 % Local Variables: % 318 % tab-width: 4 % 319 % End: % -
doc/theses/colby_parsons_MMAth/text/mutex_stmt.tex
ra50fdfb r6e1e2d0 5 5 % ====================================================================== 6 6 7 The mutex statement is a concurrent language feature that aims to support easy lock usage. 8 The mutex statement is in the form of a clause and following statement, similar to a loop or conditional statement. 9 In the clause the mutex statement accepts a number of lockable objects, and then locks them for the duration of the following statement. 10 The locks are acquired in a deadlock free manner and released using \gls{raii}. 11 The mutex statement provides an avenue for easy lock usage in the common case where locks are used to wrap a critical section. 12 Additionally, it provides the safety guarantee of deadlock-freedom, both by acquiring the locks in a deadlock-free manner, and by ensuring that the locks release on error, or normal program execution via \gls{raii}. 13 14 \begin{cfa}[tabsize=3,caption={\CFA mutex statement usage},label={l:cfa_mutex_ex}] 7 The mutual exclusion problem was introduced by Dijkstra in 1965~\cite{Dijkstra65,Dijkstra65a}. 8 There are several concurrent processes or threads that communicate by shared variables and from time to time need exclusive access to shared resources. 9 A shared resource and code manipulating it form a pairing called a \Newterm{critical section (CS)}, which is a many-to-one relationship; 10 \eg if multiple files are being written to by multiple threads, only the pairings of simultaneous writes to the same files are CSs. 11 Regions of code where the thread is not interested in the resource are combined into the \Newterm{non-critical section (NCS)}. 12 13 Exclusive access to a resource is provided by \Newterm{mutual exclusion (MX)}. 14 MX is implemented by some form of \emph{lock}, where the CS is bracketed by lock procedures @acquire@ and @release@. 15 Threads execute a loop of the form: 16 \begin{cfa} 17 loop of $thread$ p: 18 NCS; 19 acquire( lock ); CS; release( lock ); // protected critical section with MX 20 end loop. 21 \end{cfa} 22 MX guarantees there is never more than one thread in the CS. 23 MX must also guarantee eventual progress: when there are competing threads attempting access, eventually some competing thread succeeds, \ie acquires the CS, releases it, and returns to the NCS. 24 % Lamport \cite[p.~329]{Lam86mx} extends this requirement to the exit protocol. 25 A stronger constraint is that every thread that calls @acquire@ eventually succeeds after some reasonable bounded time. 26 27 \section{Monitor} 28 \CFA provides a high-level locking object, called a \Newterm{monitor}, an elegant, efficient, high-level mechanisms for mutual exclusion and synchronization for shared-memory systems. 29 First proposed by Brinch Hansen~\cite{Hansen73} and later described and extended by C.A.R.~Hoare~\cite{Hoare74}, several concurrent programming languages provide monitors as an explicit language construct: \eg Concurrent Pascal~\cite{ConcurrentPascal}, Mesa~\cite{Mesa}, Turing~\cite{Turing:old}, Modula-3~\cite{Modula-3}, \uC~\cite{Buhr92a} and Java~\cite{Java}. 30 In addition, operating-system kernels and device drivers have a monitor-like structure, although they often use lower-level primitives such as mutex locks or semaphores to manually implement a monitor. 31 32 Figure~\ref{f:AtomicCounter} shows a \CFA and Java monitor implementing an atomic counter. 33 A \Newterm{monitor} is a programming technique that implicitly binds mutual exclusion to static function scope by call and return. 34 Lock mutual exclusion, defined by acquire/release calls, is independent of lexical context (analogous to block versus heap storage allocation). 35 Restricting acquire and release points in a monitor eases programming, comprehension, and maintenance, at a slight cost in flexibility and efficiency. 36 Ultimately, a monitor is implemented using a combination of basic locks and atomic instructions. 37 38 \begin{figure} 39 \centering 40 41 \begin{lrbox}{\myboxA} 42 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 43 @monitor@ Aint { 44 int cnt; 45 }; 46 int ++?( Aint & @mutex@ m ) { return ++m.cnt; } 47 int ?=?( Aint & @mutex@ l, int r ) { l.cnt = r; } 48 int ?=?(int & l, Aint & r) { l = r.cnt; } 49 50 int i = 0, j = 0; 51 Aint x = { 0 }, y = { 0 }; $\C[1.5in]{// no mutex}$ 52 ++x; ++y; $\C{// mutex}$ 53 x = 2; y = i; $\C{// mutex}$ 54 i = x; j = y; $\C{// no mutex}\CRT$ 55 \end{cfa} 56 \end{lrbox} 57 58 \begin{lrbox}{\myboxB} 59 \begin{java}[aboveskip=0pt,belowskip=0pt] 60 class Aint { 61 private int cnt; 62 public Aint( int init ) { cnt = init; } 63 @synchronized@ public int inc() { return ++cnt; } 64 @synchronized@ public void set( int r ) {cnt = r;} 65 public int get() { return cnt; } 66 } 67 int i = 0, j = 0; 68 Aint x = new Aint( 0 ), y = new Aint( 0 ); 69 x.inc(); y.inc(); 70 x.set( 2 ); y.set( i ); 71 i = x.get(); j = y.get(); 72 \end{java} 73 \end{lrbox} 74 75 \subfloat[\CFA]{\label{f:AtomicCounterCFA}\usebox\myboxA} 76 \hspace*{3pt} 77 \vrule 78 \hspace*{3pt} 79 \subfloat[Java]{\label{f:AtomicCounterJava}\usebox\myboxB} 80 \caption{Atomic integer counter} 81 \label{f:AtomicCounter} 82 \end{figure} 83 84 Like Java, \CFA monitors have \Newterm{multi-acquire} semantics so the thread in the monitor may acquire it multiple times without deadlock, allowing recursion and calling other MX functions. 85 For robustness, \CFA monitors ensure the monitor lock is released regardless of how an acquiring function ends, normal or exceptional, and returning a shared variable is safe via copying before the lock is released. 86 Monitor objects can be passed through multiple helper functions without acquiring mutual exclusion, until a designated function associated with the object is called. 87 \CFA functions are designated MX by one or more pointer/reference parameters having qualifier @mutex@. 88 Java members are designated MX with \lstinline[language=java]{synchronized}, which applies only to the implicit receiver parameter. 89 In the example, the increment and setter operations need mutual exclusion, while the read-only getter operation is not MX because reading an integer is atomic. 90 91 As stated, the non-object-oriented nature of \CFA monitors allows a function to acquire multiple mutex objects. 92 For example, the bank-transfer problem requires locking two bank accounts to safely debit and credit money between accounts. 93 \begin{cfa} 94 monitor BankAccount { 95 int balance; 96 }; 97 void deposit( BankAccount & mutex b, int deposit ) with( b ) { 98 balance += deposit; 99 } 100 void transfer( BankAccount & mutex my, BankAccount & mutex your, int me2you ) { 101 deposit( my, -me2you ); $\C{// debit}$ 102 deposit( your, me2you ); $\C{// credit}$ 103 } 104 \end{cfa} 105 The \CFA monitor implementation ensures multi-lock acquisition is done in a deadlock-free manner regardless of the number of MX parameters and monitor arguments. 106 107 108 \section{\lstinline{mutex} statement} 109 Restricting implicit lock acquisition to function entry and exit can be awkward for certain problems. 110 To increase locking flexibility, some languages introduce a mutex statement. 111 \VRef[Figure]{f:ReadersWriter} shows the outline of a reader/writer lock written as a \CFA monitor and mutex statements. 112 (The exact lock implement is irrelevant.) 113 The @read@ and @write@ functions are called with a reader/write lock and any arguments to perform reading or writing. 114 The @read@ function is not MX because multiple readers can read simultaneously. 115 MX is acquired within @read@ by calling the (nested) helper functions @StartRead@ and @EndRead@ or executing the mutex statements. 116 Between the calls or statements, reads can execute simultaneous within the body of @read@. 117 The @write@ function does not require refactoring because writing is a CS. 118 The mutex-statement version is better because it has fewer names, less argument/parameter passing, and can possibly hold MX for a shorter duration. 119 120 \begin{figure} 121 \centering 122 123 \begin{lrbox}{\myboxA} 124 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 125 monitor RWlock { ... }; 126 void read( RWlock & rw, ... ) { 127 void StartRead( RWlock & @mutex@ rw ) { ... } 128 void EndRead( RWlock & @mutex@ rw ) { ... } 129 StartRead( rw ); 130 ... // read without MX 131 EndRead( rw ); 132 } 133 void write( RWlock & @mutex@ rw, ... ) { 134 ... // write with MX 135 } 136 \end{cfa} 137 \end{lrbox} 138 139 \begin{lrbox}{\myboxB} 140 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 141 142 void read( RWlock & rw, ... ) { 143 144 145 @mutex@( rw ) { ... } 146 ... // read without MX 147 @mutex@{ rw ) { ... } 148 } 149 void write( RWlock & @mutex@ rw, ... ) { 150 ... // write with MX 151 } 152 \end{cfa} 153 \end{lrbox} 154 155 \subfloat[monitor]{\label{f:RWmonitor}\usebox\myboxA} 156 \hspace*{3pt} 157 \vrule 158 \hspace*{3pt} 159 \subfloat[mutex statement]{\label{f:RWmutexstmt}\usebox\myboxB} 160 \caption{Readers writer problem} 161 \label{f:ReadersWriter} 162 \end{figure} 163 164 This work adds a mutex statement to \CFA, but generalizes it beyond implicit monitor locks. 165 In detail, the mutex statement has a clause and statement block, similar to a conditional or loop statement. 166 The clause accepts any number of lockable objects (like a \CFA MX function prototype), and locks them for the duration of the statement. 167 The locks are acquired in a deadlock free manner and released regardless of how control-flow exits the statement. 168 The mutex statement provides easy lock usage in the common case of lexically wrapping a CS. 169 Examples of \CFA mutex statement are shown in \VRef[Listing]{l:cfa_mutex_ex}. 170 171 \begin{cfa}[caption={\CFA mutex statement usage},label={l:cfa_mutex_ex}] 15 172 owner_lock lock1, lock2, lock3; 16 int count = 0; 17 mutex( lock1, lock2, lock3 ) { 18 // can use block statement 19 // ... 20 } 21 mutex( lock2, lock3 ) count++; // or inline statement 173 @mutex@( lock2, lock3 ) ...; $\C{// inline statement}$ 174 @mutex@( lock1, lock2, lock3 ) { ... } $\C{// statement block}$ 175 void transfer( BankAccount & my, BankAccount & your, int me2you ) { 176 ... // check values, no MX 177 @mutex@( my, your ) { // MX is shorter duration that function body 178 deposit( my, -me2you ); $\C{// debit}$ 179 deposit( your, me2you ); $\C{// credit}$ 180 } 181 } 22 182 \end{cfa} 23 183 24 184 \section{Other Languages} 25 There are similar concepts to the mutex statement that exist in other languages. 26 Java has a feature called a synchronized statement, which looks identical to \CFA's mutex statement, but it has some differences. 27 The synchronized statement only accepts a single object in its clause. 28 Any object can be passed to the synchronized statement in Java since all objects in Java are monitors, and the synchronized statement acquires that object's monitor. 29 In \CC there is a feature in the standard library \code{<mutex>} header called scoped\_lock, which is also similar to the mutex statement. 30 The scoped\_lock is a class that takes in any number of locks in its constructor, and acquires them in a deadlock-free manner. 31 It then releases them when the scoped\_lock object is deallocated, thus using \gls{raii}. 32 An example of \CC scoped\_lock usage is shown in Listing~\ref{l:cc_scoped_lock}. 33 34 \begin{cfa}[tabsize=3,caption={\CC scoped\_lock usage},label={l:cc_scoped_lock}] 35 std::mutex lock1, lock2, lock3; 36 { 37 scoped_lock s( lock1, lock2, lock3 ) 38 // locks are released via raii at end of scope 39 } 185 There are similar constructs to the mutex statement in other programming languages. 186 Java has a feature called a synchronized statement, which looks like the \CFA's mutex statement, but only accepts a single object in the clause and only handles monitor locks. 187 The \CC standard library has a @scoped_lock@, which is also similar to the mutex statement. 188 The @scoped_lock@ takes any number of locks in its constructor, and acquires them in a deadlock-free manner. 189 It then releases them when the @scoped_lock@ object is deallocated using \gls{raii}. 190 An example of \CC @scoped_lock@ is shown in \VRef[Listing]{l:cc_scoped_lock}. 191 192 \begin{cfa}[caption={\CC \lstinline{scoped_lock} usage},label={l:cc_scoped_lock}] 193 struct BankAccount { 194 @recursive_mutex m;@ $\C{// must be recursive}$ 195 int balance = 0; 196 }; 197 void deposit( BankAccount & b, int deposit ) { 198 @scoped_lock lock( b.m );@ $\C{// RAII acquire}$ 199 b.balance += deposit; 200 } $\C{// RAII release}$ 201 void transfer( BankAccount & my, BankAccount & your, int me2you ) { 202 @scoped_lock lock( my.m, your.m );@ $\C{// RAII acquire}$ 203 deposit( my, -me2you ); $\C{// debit}$ 204 deposit( your, me2you ); $\C{// credit}$ 205 } $\C{// RAII release}$ 40 206 \end{cfa} 41 207 42 208 \section{\CFA implementation} 43 The \CFA mutex statement takes some ideas from both the Java and \CC features. 44 The mutex statement can acquire more that one lock in a deadlock-free manner, and releases them via \gls{raii} like \CC, however the syntax is identical to the Java synchronized statement. 45 This syntactic choice was made so that the body of the mutex statement is its own scope. 46 Compared to the scoped\_lock, which relies on its enclosing scope, the mutex statement's introduced scope can provide visual clarity as to what code is being protected by the mutex statement, and where the mutual exclusion ends. 47 \CFA's mutex statement and \CC's scoped\_lock both use parametric polymorphism to allow user defined types to work with the feature. 48 \CFA's implementation requires types to support the routines \code{lock()} and \code{unlock()}, whereas \CC requires those routines, plus \code{try_lock()}. 49 The scoped\_lock requires an additional routine since it differs from the mutex statement in how it implements deadlock avoidance. 50 51 The parametric polymorphism allows for locking to be defined for types that may want convenient mutual exclusion. 52 An example of one such use case in \CFA is \code{sout}. 53 The output stream in \CFA is called \code{sout}, and functions similarly to \CC's \code{cout}. 54 \code{sout} has routines that satisfy the mutex statement trait, so the mutex statement can be used to lock the output stream while producing output. 55 In this case, the mutex statement allows the programmer to acquire mutual exclusion over an object without having to know the internals of the object or what locks need to be acquired. 56 The ability to do so provides both improves safety and programmer productivity since it abstracts away the concurrent details and provides an interface for optional thread-safety. 57 This is a commonly used feature when producing output from a concurrent context, since producing output is not thread safe by default. 58 This use case is shown in Listing~\ref{l:sout}. 59 60 \begin{cfa}[tabsize=3,caption={\CFA sout with mutex statement},label={l:sout}] 61 mutex( sout ) 62 sout | "This output is protected by mutual exclusion!"; 63 \end{cfa} 64 65 \section{Deadlock Avoidance} 66 The mutex statement uses the deadlock prevention technique of lock ordering, where the circular-wait condition of a deadlock cannot occur if all locks are acquired in the same order. 67 The scoped\_lock uses a deadlock avoidance algorithm where all locks after the first are acquired using \code{try_lock} and if any of the attempts to lock fails, all locks so far are released. 68 This repeats until all locks are acquired successfully. 69 The deadlock avoidance algorithm used by scoped\_lock is shown in Listing~\ref{l:cc_deadlock_avoid}. 70 The algorithm presented is taken directly from the source code of the \code{<mutex>} header, with some renaming and comments for clarity. 71 72 \begin{cfa}[caption={\CC scoped\_lock deadlock avoidance algorithm},label={l:cc_deadlock_avoid}] 209 The \CFA mutex statement takes some ideas from both the Java and \CC features. 210 Like Java, \CFA introduces a new statement rather than building from existing language features. 211 (\CFA has sufficient language features to mimic \CC RAII locking.) 212 This syntactic choice makes MX explicit rather than implicit via object declarations. 213 Hence, it is easier for programmers and language tools to identify MX points in a program, \eg scan for all @mutex@ parameters and statements in a body of code. 214 Furthermore, concurrent safety is provided across an entire program for the complex operation of acquiring multiple locks in a deadlock-free manner. 215 Unlike Java, \CFA's mutex statement and \CC's @scoped_lock@ both use parametric polymorphism to allow user defined types to work with this feature. 216 In this case, the polymorphism allows a locking mechanism to acquire MX over an object without having to know the object internals or what kind of lock it is using. 217 \CFA's provides and uses this locking trait: 218 \begin{cfa} 219 forall( L & | sized(L) ) 220 trait is_lock { 221 void lock( L & ); 222 void unlock( L & ); 223 }; 224 \end{cfa} 225 \CC @scoped_lock@ has this trait implicitly based on functions accessed in a template. 226 @scoped_lock@ also requires @try_lock@ because of its technique for deadlock avoidance \see{\VRef{s:DeadlockAvoidance}}. 227 228 The following shows how the @mutex@ statement is used with \CFA streams to eliminate unpredictable results when printing in a concurrent program. 229 For example, if two threads execute: 230 \begin{cfa} 231 thread$\(_1\)$ : sout | "abc" | "def"; 232 thread$\(_2\)$ : sout | "uvw" | "xyz"; 233 \end{cfa} 234 any of the outputs can appear, included a segment fault due to I/O buffer corruption: 235 \begin{cquote} 236 \small\tt 237 \begin{tabular}{@{}l|l|l|l|l@{}} 238 abc def & abc uvw xyz & uvw abc xyz def & abuvwc dexf & uvw abc def \\ 239 uvw xyz & def & & yz & xyz 240 \end{tabular} 241 \end{cquote} 242 The stream type for @sout@ is defined to satisfy the @is_lock@ trait, so the @mutex@ statement can be used to lock an output stream while producing output. 243 From the programmer's perspective, it is sufficient to know an object can be locked and then any necessary MX is easily available via the @mutex@ statement. 244 This ability improves safety and programmer productivity since it abstracts away the concurrent details. 245 Hence, a programmer can easily protect cascaded I/O expressions: 246 \begin{cfa} 247 thread$\(_1\)$ : mutex( sout ) sout | "abc" | "def"; 248 thread$\(_2\)$ : mutex( sout ) sout | "uvw" | "xyz"; 249 \end{cfa} 250 constraining the output to two different lines in either order: 251 \begin{cquote} 252 \small\tt 253 \begin{tabular}{@{}l|l@{}} 254 abc def & uvw xyz \\ 255 uvw xyz & abc def 256 \end{tabular} 257 \end{cquote} 258 where this level of safe nondeterministic output is acceptable. 259 Alternatively, multiple I/O statements can be protected using the mutex statement block: 260 \begin{cfa} 261 mutex( sout ) { // acquire stream lock for sout for block duration 262 sout | "abc"; 263 mutex( sout ) sout | "uvw" | "xyz"; // OK because sout lock is recursive 264 sout | "def"; 265 } // implicitly release sout lock 266 \end{cfa} 267 The inner lock acquire is likely to occur through a function call that does a thread-safe print. 268 269 \section{Deadlock Avoidance}\label{s:DeadlockAvoidance} 270 The mutex statement uses the deadlock avoidance technique of lock ordering, where the circular-wait condition of a deadlock cannot occur if all locks are acquired in the same order. 271 The @scoped_lock@ uses a deadlock avoidance algorithm where all locks after the first are acquired using @try_lock@ and if any of the lock attempts fail, all acquired locks are released. 272 This repeats after selecting a new starting point in a cyclic manner until all locks are acquired successfully. 273 This deadlock avoidance algorithm is shown in Listing~\ref{l:cc_deadlock_avoid}. 274 The algorithm is taken directly from the source code of the @<mutex>@ header, with some renaming and comments for clarity. 275 276 \begin{cfa}[caption={\CC \lstinline{scoped_lock} deadlock avoidance algorithm},label={l:cc_deadlock_avoid}] 73 277 int first = 0; // first lock to attempt to lock 74 278 do { 75 76 locks[first].lock(); // lock first lock 77 for (int i = 1; i < Num_Locks; ++i) { // iterate over rest of locks 78 79 if (!locks[idx].try_lock()) { // try lock each one 80 for (int j = i; j != 0; --j) // release all locks 81 82 first = idx; // rotate which lock to acquire first 83 84 85 279 // locks is the array of locks to acquire 280 locks[first].lock(); $\C{// lock first lock}$ 281 for ( int i = 1; i < Num_Locks; i += 1 ) { $\C{// iterate over rest of locks}$ 282 const int idx = (first + i) % Num_Locks; 283 if ( ! locks[idx].try_lock() ) { $\C{// try lock each one}$ 284 for ( int j = i; j != 0; j -= 1 ) $\C{// release all locks}$ 285 locks[(first + j - 1) % Num_Locks].unlock(); 286 first = idx; $\C{// rotate which lock to acquire first}$ 287 break; 288 } 289 } 86 290 // if first lock is still held then all have been acquired 87 } while (!locks[first].owns_lock()); // is first lock held? 88 \end{cfa} 89 90 The algorithm in \ref{l:cc_deadlock_avoid} successfully avoids deadlock, however there is a potential livelock scenario. 91 Given two threads $A$ and $B$, who create a scoped\_lock with two locks $L1$ and $L2$, a livelock can form as follows. 92 Thread $A$ creates a scoped\_lock with $L1$, $L2$, and $B$ creates a scoped lock with the order $L2$, $L1$. 93 Both threads acquire the first lock in their order and then fail the try\_lock since the other lock is held. 94 They then reset their start lock to be their 2nd lock and try again. 95 This time $A$ has order $L2$, $L1$, and $B$ has order $L1$, $L2$. 96 This is identical to the starting setup, but with the ordering swapped among threads. 97 As such, if they each acquire their first lock before the other acquires their second, they can livelock indefinitely. 98 99 The lock ordering algorithm used in the mutex statement in \CFA is both deadlock and livelock free. 100 It sorts the locks based on memory address and then acquires them. 101 For locks fewer than 7, it sorts using hard coded sorting methods that perform the minimum number of swaps for a given number of locks. 102 For 7 or more locks insertion sort is used. 103 These sorting algorithms were chosen since it is rare to have to hold more than a handful of locks at a time. 104 It is worth mentioning that the downside to the sorting approach is that it is not fully compatible with usages of the same locks outside the mutex statement. 105 If more than one lock is held by a mutex statement, if more than one lock is to be held elsewhere, it must be acquired via the mutex statement, or else the required ordering will not occur. 106 Comparitively, if the scoped\_lock is used and the same locks are acquired elsewhere, there is no concern of the scoped\_lock deadlocking, due to its avoidance scheme, but it may livelock. 291 } while ( ! locks[first].owns_lock() ); $\C{// is first lock held?}$ 292 \end{cfa} 293 294 While the algorithm in \ref{l:cc_deadlock_avoid} successfully avoids deadlock, there is a livelock scenario. 295 Assume two threads, $A$ and $B$, create a @scoped_lock@ accessing two locks, $L1$ and $L2$. 296 A livelock can form as follows. 297 Thread $A$ creates a @scoped_lock@ with arguments $L1$, $L2$, and $B$ creates a scoped lock with the lock arguments in the opposite order $L2$, $L1$. 298 Both threads acquire the first lock in their order and then fail the @try_lock@ since the other lock is held. 299 Both threads then reset their starting lock to be their second lock and try again. 300 This time $A$ has order $L2$, $L1$, and $B$ has order $L1$, $L2$, which is identical to the starting setup but with the ordering swapped between threads. 301 If the threads perform this action in lock-step, they cycle indefinitely without entering the CS, \ie livelock. 302 Hence, to use @scoped_lock@ safely, a programmer must manually construct and maintain a global ordering of lock arguments passed to @scoped_lock@. 303 304 The lock ordering algorithm used in \CFA mutex functions and statements is deadlock and livelock free. 305 The algorithm uses the lock memory addresses as keys, sorts the keys, and then acquires the locks in sorted order. 306 For fewer than 7 locks ($2^3-1$), the sort is unrolled performing the minimum number of compare and swaps for the given number of locks; 307 for 7 or more locks, insertion sort is used. 308 Since it is extremely rare to hold more than 6 locks at a time, the algorithm is fast and executes in $O(1)$ time. 309 Furthermore, lock addresses are unique across program execution, even for dynamically allocated locks, so the algorithm is safe across the entire program execution. 310 311 The downside to the sorting approach is that it is not fully compatible with manual usages of the same locks outside the @mutex@ statement, \ie the lock are acquired without using the @mutex@ statement. 312 The following scenario is a classic deadlock. 313 \begin{cquote} 314 \begin{tabular}{@{}l@{\hspace{30pt}}l@{}} 315 \begin{cfa} 316 lock L1, L2; // assume &L1 < &L2 317 $\textbf{thread\(_1\)}$ 318 acquire( L2 ); 319 acquire( L1 ); 320 CS 321 release( L1 ); 322 release( L2 ); 323 \end{cfa} 324 & 325 \begin{cfa} 326 327 $\textbf{thread\(_2\)}$ 328 mutex( L1, L2 ) { 329 330 CS 331 332 } 333 \end{cfa} 334 \end{tabular} 335 \end{cquote} 336 Comparatively, if the @scoped_lock@ is used and the same locks are acquired elsewhere, there is no concern of the @scoped_lock@ deadlocking, due to its avoidance scheme, but it may livelock. 337 The convenience and safety of the @mutex@ statement, \eg guaranteed lock release with exceptions, should encourage programmers to always use it for locking, mitigating any deadlock scenario. 338 339 \section{Performance} 340 Given the two multi-acquisition algorithms in \CC and \CFA, each with differing advantages and disadvantages, it interesting to compare their performance. 341 Comparison with Java is not possible, since it only takes a single lock. 342 343 The comparison starts with a baseline that acquires the locks directly without a mutex statement or @scoped_lock@ in a fixed ordering and then releases them. 344 The baseline helps highlight the cost of the deadlock avoidance/prevention algorithms for each implementation. 345 346 The benchmark used to evaluate the avoidance algorithms repeatedly acquires a fixed number of locks in a random order and then releases them. 347 The pseudo code for the deadlock avoidance benchmark is shown in \VRef[Listing]{l:deadlock_avoid_pseudo}. 348 To ensure the comparison exercises the implementation of each lock avoidance algorithm, an identical spinlock is implemented in each language using a set of builtin atomics available in both \CC and \CFA. 349 The benchmarks are run for a fixed duration of 10 seconds and then terminate. 350 The total number of times the group of locks is acquired is returned for each thread. 351 Each variation is run 11 times on 2, 4, 8, 16, 24, 32 cores and with 2, 4, and 8 locks being acquired. 352 The median is calculated and is plotted alongside the 95\% confidence intervals for each point. 353 354 \begin{cfa}[caption={Deadlock avoidance bendchmark pseudo code},label={l:deadlock_avoid_pseudo}] 355 356 357 358 $\PAB{// add pseudo code}$ 359 360 361 362 \end{cfa} 363 364 The performance experiments were run on the following multi-core hardware systems to determine differences across platforms: 365 \begin{list}{\arabic{enumi}.}{\usecounter{enumi}\topsep=5pt\parsep=5pt\itemsep=0pt} 366 % sudo dmidecode -t system 367 \item 368 Supermicro AS--1123US--TR4 AMD EPYC 7662 64--core socket, hyper-threading $\times$ 2 sockets (256 processing units) 2.0 GHz, TSO memory model, running Linux v5.8.0--55--generic, gcc--10 compiler 369 \item 370 Supermicro SYS--6029U--TR4 Intel Xeon Gold 5220R 24--core socket, hyper-threading $\times$ 2 sockets (48 processing units) 2.2GHz, TSO memory model, running Linux v5.8.0--59--generic, gcc--10 compiler 371 \end{list} 372 %The hardware architectures are different in threading (multithreading vs hyper), cache structure (MESI or MESIF), NUMA layout (QPI vs HyperTransport), memory model (TSO vs WO), and energy/thermal mechanisms (turbo-boost). 373 %Software that runs well on one architecture may run poorly or not at all on another. 374 375 Figure~\ref{f:mutex_bench} shows the results of the benchmark experiments. 376 \PAB{Make the points in the graphs for each line different. 377 Also, make the text in the graphs larger.} 378 The baseline results for both languages are mostly comparable, except for the 8 locks results in \ref{f:mutex_bench8_AMD} and \ref{f:mutex_bench8_Intel}, where the \CFA baseline is slightly slower. 379 The avoidance result for both languages is significantly different, where \CFA's mutex statement achieves throughput that is magnitudes higher than \CC's @scoped_lock@. 380 The slowdown for @scoped_lock@ is likely due to its deadlock-avoidance implementation. 381 Since it uses a retry based mechanism, it can take a long time for threads to progress. 382 Additionally the potential for livelock in the algorithm can result in very little throughput under high contention. 383 For example, on the AMD machine with 32 threads and 8 locks, the benchmarks would occasionally livelock indefinitely, with no threads making any progress for 3 hours before the experiment was terminated manually. 384 It is likely that shorter bouts of livelock occurred in many of the experiments, which would explain large confidence intervals for some of the data points in the \CC data. 385 In Figures~\ref{f:mutex_bench8_AMD} and \ref{f:mutex_bench8_Intel} the mutex statement performs better than the baseline. 386 At 7 locks and above the mutex statement switches from a hard coded sort to insertion sort. 387 It is likely that the improvement in throughput compared to baseline is due to the time spent in the insertion sort, which decreases contention on the locks. 107 388 108 389 \begin{figure} 109 \centering 110 \begin{subfigure}{0.5\textwidth} 111 \centering 112 \scalebox{0.5}{\input{figures/nasus_Aggregate_Lock_2.pgf}} 113 \subcaption{AMD} 114 \end{subfigure}\hfill 115 \begin{subfigure}{0.5\textwidth} 116 \centering 117 \scalebox{0.5}{\input{figures/pyke_Aggregate_Lock_2.pgf}} 118 \subcaption{Intel} 119 \end{subfigure} 120 121 \begin{subfigure}{0.5\textwidth} 122 \centering 123 \scalebox{0.5}{\input{figures/nasus_Aggregate_Lock_4.pgf}} 124 \subcaption{AMD} 125 \end{subfigure}\hfill 126 \begin{subfigure}{0.5\textwidth} 127 \centering 128 \scalebox{0.5}{\input{figures/pyke_Aggregate_Lock_4.pgf}} 129 \subcaption{Intel} 130 \end{subfigure} 131 132 \begin{subfigure}{0.5\textwidth} 133 \centering 134 \scalebox{0.5}{\input{figures/nasus_Aggregate_Lock_8.pgf}} 135 \subcaption{AMD}\label{f:mutex_bench8_AMD} 136 \end{subfigure}\hfill 137 \begin{subfigure}{0.5\textwidth} 138 \centering 139 \scalebox{0.5}{\input{figures/pyke_Aggregate_Lock_8.pgf}} 140 \subcaption{Intel}\label{f:mutex_bench8_Intel} 141 \end{subfigure} 142 \caption{The aggregate lock benchmark comparing \CC scoped\_lock and \CFA mutex statement throughput (higher is better).} 143 \label{f:mutex_bench} 390 \centering 391 \subfloat[AMD]{ 392 \resizebox{0.5\textwidth}{!}{\input{figures/nasus_Aggregate_Lock_2.pgf}} 393 } 394 \subfloat[Intel]{ 395 \resizebox{0.5\textwidth}{!}{\input{figures/pyke_Aggregate_Lock_2.pgf}} 396 } 397 398 \subfloat[AMD]{ 399 \resizebox{0.5\textwidth}{!}{\input{figures/nasus_Aggregate_Lock_4.pgf}} 400 } 401 \subfloat[Intel]{ 402 \resizebox{0.5\textwidth}{!}{\input{figures/pyke_Aggregate_Lock_4.pgf}} 403 } 404 405 \subfloat[AMD]{ 406 \resizebox{0.5\textwidth}{!}{\input{figures/nasus_Aggregate_Lock_8.pgf}} 407 \label{f:mutex_bench8_AMD} 408 } 409 \subfloat[Intel]{ 410 \resizebox{0.5\textwidth}{!}{\input{figures/pyke_Aggregate_Lock_8.pgf}} 411 \label{f:mutex_bench8_Intel} 412 } 413 \caption{The aggregate lock benchmark comparing \CC \lstinline{scoped_lock} and \CFA mutex statement throughput (higher is better).} 414 \label{f:mutex_bench} 144 415 \end{figure} 145 416 146 \section{Performance} 147 Performance is compared between \CC's scoped\_lock and \CFA's mutex statement. 148 Comparison with Java is omitted, since it only takes a single lock. 149 To ensure that the comparison between \CC and \CFA exercises the implementation of each feature, an identical spinlock is implemented in each language using a set of builtin atomics available in both \CFA and \CC. 150 Each feature is evaluated on a benchmark which acquires a fixed number of locks in a random order and then releases them. 151 A baseline is included that acquires the locks directly without a mutex statement or scoped\_lock in a fixed ordering and then releases them. 152 The baseline helps highlight the cost of the deadlock avoidance/prevention algorithms for each implementation. 153 The benchmarks are run for a fixed duration of 10 seconds and then terminate and return the total number of times the group of locks were acquired. 154 Each variation is run 11 times on a variety up to 32 cores and with 2, 4, and 8 locks being acquired. 155 The median is calculated and is plotted alongside the 95\% confidence intervals for each point. 156 157 Figure~\ref{f:mutex_bench} shows the results of the benchmark. 158 The baseline runs for both languages are mostly comparable, except for the 8 locks results in \ref{f:mutex_bench8_AMD} and \ref{f:mutex_bench8_Intel}, where the \CFA baseline is slower. 159 \CFA's mutex statement achieves throughput that is magnitudes higher than \CC's scoped\_lock. 160 This is likely due to the scoped\_lock deadlock avoidance implementation. 161 Since it uses a retry based mechanism, it can take a long time for threads to progress. 162 Additionally the potential for livelock in the algorithm can result in very little throughput under high contention. 163 It was observed on the AMD machine that with 32 threads and 8 locks the benchmarks would occasionally livelock indefinitely, with no threads making any progress for 3 hours before the experiment was terminated manually. 164 It is likely that shorter bouts of livelock occured in many of the experiments, which would explain large confidence intervals for some of the data points in the \CC data. 165 In Figures~\ref{f:mutex_bench8_AMD} and \ref{f:mutex_bench8_Intel} the mutex statement performs better than the baseline. 166 At 7 locks and above the mutex statement switches from a hard coded sort to insertion sort. 167 It is likely that the improvement in throughput compared to baseline is due to the time spent in the insertion sort, which decreases contention on the locks. 417 % Local Variables: % 418 % tab-width: 4 % 419 % End: % -
doc/theses/colby_parsons_MMAth/thesis.tex
ra50fdfb r6e1e2d0 84 84 \usepackage{tikz} % for diagrams and figures 85 85 \def\checkmark{\tikz\fill[scale=0.4](0,.35) -- (.25,0) -- (1,.7) -- (.25,.15) -- cycle;} 86 \usepackage{subcaption}87 86 \usepackage{fullpage,times,comment} 88 87 \usepackage{textcomp} 89 88 \usepackage{graphicx} 90 89 \usepackage{tabularx} 90 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt,font=normalsize]{subfig} 91 \renewcommand\thesubfigure{(\alph{subfigure})} 91 92 \input{style} 92 93 -
doc/theses/colby_parsons_MMAth/version.sh
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
doc/theses/mike_brooks_MMath/benchmarks/list/Makefile
ra50fdfb r6e1e2d0 1 1 # For correctness, see test-correctness.sh. 2 2 # For performance: 3 # pushd ~/cfax 4 # ~/setcfa build-fast 5 # popd 6 # make perfprogs CFA=$cfa -j8 MODE=performance 7 # make results-latest.csv RUNARGS=5 RUN_NUM_REPS=5 8 3 # pushd ~/cfax 4 # . ~/setcfa build-fast 5 # popd 6 # make perfprogs CFA=$cfa -j8 MODE=performance 7 # make results-latest.csv RUN_DURATION_SEC=5 RUN_NUM_REPS=5 RUN_DATA_SIZE_MODE=common5 8 # cp results-latest.csv results-baseline.csv 9 # make results-latest.csv OP_MOVEMENTS=stack OP_POLARITIES=insfirst OP_ACCESSORS=allhead RUN_DURATION_SEC=5 RUN_NUM_REPS=5 RUN_DATA_SIZE_MODE=thorough 10 # cp results-latest.csv results-sizing.csv 9 11 10 12 CFA = cfa … … 12 14 UXX = ~/u++/u++-7.0.0/bin/u++ 13 15 14 MODE = performance 15 RUNARGS= 16 MODE=performance 17 EXTRA_COMP_FLAGS= 18 RUN_NUM_REPS=3 19 RUN_DATA_SIZE_MODE=none 20 RUN_DURATION_SEC=5 21 RUN_TASKSET_CPULIST=6 16 22 17 23 ifeq "$(MODE)" "performance" 18 PERFFLAGS_CFA = - nodebug -O324 PERFFLAGS_CFA = -DNDEBUG -O3 -nodebug 19 25 PERFFLAGS_CC = -DNDEBUG -O3 20 26 else ifeq "$(MODE)" "correctness" 21 PERFFLAGS_CFA = - debug -O0 -g22 PERFFLAGS_CC = -O0 -g27 PERFFLAGS_CFA = -O0 -g -debug 28 PERFFLAGS_CC = -O0 -g 23 29 else 24 30 $(error Bad MODE ($(MODE)); should be performance or correctness) … … 26 32 27 33 PERFFLAGS_CXX = $(PERFFLAGS_CC) 28 PERFFLAGS_UXX = $(PERFFLAGS_CC) 34 PERFFLAGS_UXX = $(PERFFLAGS_CFA) 35 36 CFLAGS=$(PERFFLAGS_CC) $(EXTRA_COMP_FLAGS) 29 37 30 38 SHELL = /usr/bin/bash … … 101 109 perfexp--% driver--%.o : COMPILER=NO-COMPILER-FOR-$(FX_COARSE) 102 110 111 # Without this %.d rule, ordinary make runs have noise about the recipe for driver--%.o being ill-formed when called on a *.d. 112 # https://stackoverflow.com/questions/3714041/why-does-this-makefile-execute-a-target-on-make-clean 113 # Whatever you -include gets called as a target first. 114 # One such example is driver--upp-upp--stack-insfirst-allhead.d 115 # Without this %.d rule, `make make driver--upp-upp--stack-insfirst-allhead.d` leads to the rule for driver--%.o firing. 116 # Though my dumb human eyes don't see the pattern as matching. 117 %.d: 118 @touch $@ 119 103 120 perfexp--% : driver--%.o observation.o 104 $(COMPILER) $ ^ -o $@121 $(COMPILER) $(EXTRA_COMP_FLAGS) $^ -o $@ 105 122 106 123 driver--%.o : driver.c 107 $(COMPILER) -c $< $(OP_DEFINES) -include op-$(OP).h -include fx-$(FX).h -o $@ -MMD 108 109 110 111 112 RUN_NUM_REPS=3 124 $(COMPILER) $(EXTRA_COMP_FLAGS) -c $< $(OP_DEFINES) -include op-$(OP).h -include fx-$(FX).h -o $@ -MMD 125 126 sayhi: 127 echo $(PERFPROGS) 128 129 130 ifeq "$(RUN_DATA_SIZE_MODE)" "common5" 131 RUN_DATA_SIZES=\ 132 7-1000000 \ 133 71-100000 \ 134 809-10000 \ 135 9051-1000 \ 136 72421-100 137 else ifeq "$(RUN_DATA_SIZE_MODE)" "thorough" 138 RUN_DATA_SIZES=\ 139 7-1000000 \ 140 11-100000 \ 141 13-100000 \ 142 19-100000 \ 143 29-100000 \ 144 37-100000 \ 145 53-100000 \ 146 71-100000 \ 147 101-10000 \ 148 149-10000 \ 149 211-10000 \ 150 283-10000 \ 151 401-10000 \ 152 569-10000 \ 153 809-10000 \ 154 1151-1000 \ 155 1601-1000 \ 156 2267-1000 \ 157 3203-1000 \ 158 4547-1000 \ 159 6473-1000 \ 160 9051-1000 \ 161 12809-100 \ 162 18119-100 \ 163 25601-100 \ 164 36209-100 \ 165 51203-100 \ 166 72421-100 \ 167 102407-10 \ 168 144817-10 \ 169 204803-10 \ 170 289637-10 \ 171 409609-10 \ 172 579263-10 \ 173 819229-10 \ 174 1158613-1 \ 175 1638431-1 \ 176 2317057-1 \ 177 3276803-1 \ 178 4634111-1 \ 179 6553621-1 \ 180 9268211-1 181 else ifeq "$(RUN_DATA_SIZE_MODE)" "manual" 182 ifeq "$(RUN_DATA_SIZES)" "" 183 $(error RUN_DATA_SIZE_MODE is manual but RUN_DATA_SIZES not given) 184 endif 185 else ifeq "$(RUN_DATA_SIZE_MODE)" "none" 186 # Assume user manages RUN_ARGS; empty RUN_ARGS just means run with compiled-in defaults 187 RUN_DATA_SIZES=none 188 else 189 $(error Bad RUN_DATA_SIZE_MODE ($(RUN_DATA_SIZE_MODE)); should be common5, thorough or manual) 190 endif 191 113 192 RUN_REP_IDS=$(shell echo {1..$(RUN_NUM_REPS)}) # 1 2 3 114 193 RUN_REP_EXTS=$(call cross3,,run,$(RUN_REP_IDS),.1csv) # run1.1csv run2.1cav run3.1csv 115 194 116 RESULT1S=$(call cross,.,$(CORES),$(RUN_REP_EXTS)) # lq-tailq--stack-inslast-allhead.run2.1csv 195 RUN_LAUNCHES=$(call cross,--,$(RUN_DATA_SIZES),$(RUN_REP_EXTS)) 196 197 198 199 RESULT1S=$(call cross,.,$(CORES),$(RUN_LAUNCHES)) # lq-tailq--stack-inslast-allhead.run2.1csv 200 117 201 118 202 RESULT1S_SHUFD=$(shell shuf -e $(RESULT1S)) 119 203 120 204 %.1csv : CORE=$(basename $(basename $@)) 121 %.1csv : REP_ID=$(subst .run,,$(suffix $(basename $@))) 205 %.1csv : LAUNCH=$(subst .,,$(suffix $(basename $@))) 206 %.1csv : SIZING=$(call proj,--,$(LAUNCH),1) 207 %.1csv : NUMNODES=$(call proj,-,$(SIZING),1) 208 %.1csv : CHECKDONE=$(call proj,-,$(SIZING),2) 209 %.1csv : REP_ID=$(subst run,,$(call proj,--,$(LAUNCH),2)) 210 %.1csv : RUN_ARGS=$(if $(filter none,$(SIZING)),,$(RUN_DURATION_SEC) $(CHECKDONE) $(NUMNODES) -1 $(REP_ID)) # use REP_ID as seed 122 211 %.1csv : REP_TIME=$(shell date '+%F %H:%M:%S') 123 212 %.1csv : perfprogs FORCE 124 ./perfexp--$(CORE) $(RUNARGS) | xargs -n 1 printf '%s,%s,%s\n' "$(REP_TIME)" "$(REP_ID)" | tee $@ 213 taskset --cpu-list $(RUN_TASKSET_CPULIST) ./perfexp--$(CORE) $(RUN_ARGS) | xargs -n 1 printf '%s,%s,%s,%s\n' "$(REP_TIME)" "$(REP_ID)" "$(RUN_ARGS)" | tee $@ 214 125 215 126 216 BATCHTIME=$(shell date '+%F--%H-%M-%S') … … 146 236 .PRECIOUS: result--%.1csv driver--%.o perfexp--% %.o 147 237 148 149 238 -include *.d -
doc/theses/mike_brooks_MMath/benchmarks/list/_classic.c
ra50fdfb r6e1e2d0 171 171 #endif 172 172 173 174 #define Repeat( op ) for ( volatile unsigned int i = 0; i < NoOfNodes; i += 1 ) { op; } 173 volatile unsigned int t = 0; 174 volatile unsigned int i_official = 0; 175 176 #define Repeat( op ) for ( unsigned int i = 0; (i_official = i, i < NoOfNodes); i += 1 ) { op; } 175 177 176 178 int main() { … … 192 194 TAILQ_INIT(&lst); 193 195 start = clock(); 194 for ( volatile unsigned intt = 0; t < Times; t += 1 ) {196 for ( t = 0; t < Times; t += 1 ) { 195 197 Repeat( TAILQ_INSERT_TAIL( &lst, &s[i], x ) ); 196 198 Repeat( TAILQ_REMOVE( &lst, TAILQ_FIRST( &lst ), x ) ); … … 204 206 std::list<S *> lst; 205 207 start = clock(); 206 for ( volatile unsigned intt = 0; t < Times; t += 1 ) {208 for ( t = 0; t < Times; t += 1 ) { 207 209 Repeat( lst.push_back( &s[i] ) ); 208 210 Repeat( lst.pop_front() ); … … 216 218 uSequence<S> lst; 217 219 start = clock(); 218 for ( volatile unsigned intt = 0; t < Times; t += 1 ) {220 for ( t = 0; t < Times; t += 1 ) { 219 221 Repeat( lst.addTail( &s[i] ) ); 220 222 Repeat( lst.dropHead() ); … … 228 230 dlist(S) lst; 229 231 start = clock(); 230 for ( volatile unsigned intt = 0; t < Times; t += 1 ) {232 for ( t = 0; t < Times; t += 1 ) { 231 233 Repeat( insert_last( lst, s[i] ) ); 232 234 Repeat( remove( lst`first ) ); … … 240 242 Sequence(S) lst; 241 243 start = clock(); 242 for ( volatile unsigned intt = 0; t < Times; t += 1 ) {244 for ( t = 0; t < Times; t += 1 ) { 243 245 Repeat( addHead( lst, s[i] ) ); 244 246 Repeat( dropTail( lst ) ); -
doc/theses/mike_brooks_MMath/benchmarks/list/driver.c
ra50fdfb r6e1e2d0 17 17 18 18 #if defined(NDEBUG) || (defined(__cforall) && !defined(__CFA_DEBUG__)) 19 enum { DefaultNumNodes = 1000, DefaultExperimentDurSec = 1, DefaultCheck ClockFreq = 1000, DefaultExperimentDurOpCount = -1};19 enum { DefaultNumNodes = 1000, DefaultExperimentDurSec = 1, DefaultCheckDonePeriod = 1000, DefaultExperimentDurOpCount = -1, DefaultSeed = 5 }; 20 20 #define TRACE(tp) 21 21 #else 22 enum { DefaultNumNodes = 10, DefaultExperimentDurSec = 1, DefaultCheck ClockFreq = 2, DefaultExperimentDurOpCount = 20};22 enum { DefaultNumNodes = 10, DefaultExperimentDurSec = 1, DefaultCheckDonePeriod = 2, DefaultExperimentDurOpCount = 20, DefaultSeed = 5 }; 23 23 static const char * tp_filter 24 24 // = ""; … … 63 63 } 64 64 65 int bobs_getCurrent() { 65 void * bobs_getCurrentLoc() { 66 return BFX_DEREF_POS(B_UserItem, lst, observedItem); 67 } 68 int bobs_getCurrentVal() { 66 69 B_UserItem * curUI = BFX_DEREF_POS(B_UserItem, lst, observedItem); 67 70 return curUI->userdata[17]; … … 72 75 ) 73 76 77 unsigned int uDefaultPreemption() { 78 return 0; 79 } 80 74 81 int main(int argc, const char *argv[]) { 75 82 76 77 const char * usage_args = "[ExperimentDurSec [CheckClockFreq [NumNodes [ExperimentDurOpCount]]]]"; 78 const int static_arg_posns = 4; 83 const char * usage_args = "[ExperimentDurSec [CheckDonePeriod [NumNodes [ExperimentDurOpCount [Seed]]]]]"; 84 const int static_arg_posns = 5; 79 85 80 86 unsigned int ExperimentDurSec = DefaultExperimentDurSec; 81 unsigned int Check ClockFreq = DefaultCheckClockFreq;87 unsigned int CheckDonePeriod = DefaultCheckDonePeriod; 82 88 unsigned int NumNodes = DefaultNumNodes; 83 89 size_t ExperimentDurOpCount = DefaultExperimentDurOpCount; 84 85 switch ((argc < static_arg_posns) ? argc : static_arg_posns) { 86 case 5: ExperimentDurOpCount = atoi(argv[4]); 87 case 4: NumNodes = atoi(argv[3]); 88 case 3: CheckClockFreq = atoi(argv[2]); 89 case 2: ExperimentDurSec = atoi(argv[1]); 90 } 91 92 if (ExperimentDurSec == 0 || CheckClockFreq == 0 || NumNodes == 0 || ExperimentDurOpCount == 0 ) { 90 unsigned int Seed = DefaultSeed; 91 92 switch (((argc - 1) < static_arg_posns) ? (argc - 1) : static_arg_posns) { 93 case 5: Seed = atoi(argv[5]); 94 case 4: ExperimentDurOpCount = atol(argv[4]); 95 case 3: NumNodes = atoi(argv[3]); 96 case 2: CheckDonePeriod = atoi(argv[2]); 97 case 1: ExperimentDurSec = atoi(argv[1]); 98 } 99 100 if (ExperimentDurSec == 0 || CheckDonePeriod == 0 || NumNodes == 0 || ExperimentDurOpCount == 0 || Seed == 0 ) { 93 101 printf("usage: %s %s\n", argv[0], usage_args); 94 102 return -1; 95 103 } 96 104 97 ui = (B_UserItem*) malloc( NumNodes * sizeof(B_UserItem) ); 98 memset(ui, 0, NumNodes * sizeof(B_UserItem)); 99 100 listedItems = (BFX_LISTED_ELEM_T(B_UserItem)*)malloc( NumNodes * sizeof(BFX_LISTED_ELEM_T(B_UserItem)) ); 101 memset(listedItems, 0, NumNodes * sizeof(BFX_LISTED_ELEM_T(B_UserItem))); 102 105 #ifdef DISABLE_CLOCK_RECHECK 106 if (ExperimentDurSec != -1) { 107 printf("Error: experiment compiled as fixed-work only. ExperimentDurSec (currently %d) must be set to -1.\nUsage: %s %s\n", ExperimentDurSec, argv[0], usage_args); 108 return -1; 109 } 110 #endif 111 112 #ifdef DISABLE_SHUFFLING_INDIRECTION 113 #define INSERTPOS(insertNum) insertNum 114 #else 115 // To ensure random memory order of nodes being inserted, do so according to a shuffled ordering of them. 116 unsigned int * insertOrdShuf = (unsigned int *) malloc( (size_t)NumNodes * sizeof(unsigned int) ); 117 if (!insertOrdShuf) { 118 printf("malloc request for %zd bytes for insertOrdShuf refused\n", (size_t)NumNodes * (size_t)sizeof(unsigned int)); 119 return 1; 120 } 121 // Fill with the ordinals (iota) 103 122 for (int i = 0; i < NumNodes; i++) { 104 B_UserItem * curUI = & ui[i]; 123 insertOrdShuf[i] = i; 124 } 125 // Dummy "Seed" of -1 means skip the shuffle: measure overhead of insertOrdShuf indirection 126 if (Seed != -1) { 127 // Shuffle 128 srand(Seed); 129 for (unsigned int i = 0; i < NumNodes; i++) { 130 unsigned int nodesRemaining = NumNodes - i; 131 unsigned int swapWith = i + rand() % nodesRemaining; 132 unsigned int tempValue = insertOrdShuf[swapWith]; 133 insertOrdShuf[swapWith] = insertOrdShuf[i]; 134 insertOrdShuf[i] = tempValue; 135 } 136 } 137 #define INSERTPOS(insertNum) insertOrdShuf[insertNum] 138 #endif 139 140 ui = (B_UserItem*) malloc( (size_t)NumNodes * (size_t)sizeof(B_UserItem) ); 141 if (!ui) { 142 printf("malloc request for %zd bytes for ui refused\n", (size_t)NumNodes * (size_t)sizeof(B_UserItem)); 143 return 1; 144 } 145 memset(ui, 0, (size_t)NumNodes * (size_t)sizeof(B_UserItem)); 146 147 listedItems = (BFX_LISTED_ELEM_T(B_UserItem)*)malloc( (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem)) ); 148 if (!listedItems) { 149 printf("malloc request for %zd bytes for listedItems refused\n", (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem))); 150 return 1; 151 } 152 memset(listedItems, 0, (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem))); 153 154 // Fill with demo data 155 for (unsigned int i = 0; i < NumNodes; i++) { 156 B_UserItem * curUI = & ui[INSERTPOS(i)]; 105 157 curUI->userdata[17] = i; 106 158 } … … 110 162 bobs_init(NumNodes); 111 163 112 // BOP Convention: 113 // Action-number arguments are for the BOP cartridge to interpret. 114 // I.e. the driver assumes no relationship between BOP_INSERT(_,_,xx) and ui[xx]. 164 // BOP_ADDFOO(lst, iters, insNo, item) 165 // BOP_REMFOO(lst, iters, remNo) 166 // lst lvalue of the list head being added to / removed from 167 // iters array of ADD return values, in logical-insert order; on ADD, is valid at [0..insNo) 168 // insNo counter of the ADD calls (logical insert number) 169 // remNo counter of the REM calls (logical remove number) 170 // item lvalue of the item being added 115 171 // Logical insert number 0 and remove number n-1 are given with a distinguished hook. 116 172 // Logical insert numbers [1,n) and remove numbers [0,n-1) are pumped by the basic SUT hooks. 117 173 // This pattern lets BOP cartridges that measure element-level operations know statically when there is a reference element in the list. 174 // The driver owns the relationship between a logical insert number and the location of the `item` argument within `ui`. (Scattered for randomness.) 175 // The BOP cartridge owns the relationship between logical remove number and any choice of an item in iters. (Defines stack vs queue.) 118 176 119 177 // Default init/teardown is insert/remove 120 178 // Cartridges whose SUT insert/remove actions work on empty lists need not provide special-case ones. 121 179 #ifndef BOP_INIT 122 #define BOP_INIT(lst, ui, iters, i) BOP_INSERT(lst, ui, iters, i)180 #define BOP_INIT(lst, iters, insNo, item) BOP_INSERT(lst, iters, insNo, item) 123 181 #endif 124 182 #ifndef BOP_TEARDOWN 125 #define BOP_TEARDOWN(lst, ui, iters, i) BOP_REMOVE(lst, ui, iters, i)183 #define BOP_TEARDOWN(lst, iters, remNo) BOP_REMOVE(lst, iters, remNo) 126 184 #endif 127 185 … … 129 187 clock_t start = clock(); 130 188 131 while (elapsed_sec <= (double) ExperimentDurSec && bobs_ops_completed < ExperimentDurOpCount) { 132 for ( int t = 0; t < CheckClockFreq; t += 1 ) { 189 size_t privateOpsCompleted = 0; 190 191 while (elapsed_sec <= (double) ExperimentDurSec && privateOpsCompleted < ExperimentDurOpCount) { 192 for ( int t = 0; t < CheckDonePeriod; t += 1 ) { 133 193 TRACE('a') 134 194 listedItems[0] = 135 BOP_INIT(lst, ui, listedItems, 0);195 BOP_INIT(lst, listedItems, 0, ui[INSERTPOS(0)]); 136 196 TRACE('b') 137 197 for ( int privateCurInsert = 1; … … 141 201 TRACE('-') 142 202 listedItems[privateCurInsert] = 143 BOP_INSERT( lst, ui, listedItems, privateCurInsert);203 BOP_INSERT( lst, listedItems, privateCurInsert, ui[INSERTPOS(privateCurInsert)] ); 144 204 TRACE('+') 145 205 } … … 150 210 ) { 151 211 TRACE('-') 152 BOP_REMOVE( lst, ui,listedItems, privateCurRemove-1 );212 BOP_REMOVE( lst, listedItems, privateCurRemove-1 ); 153 213 TRACE('+') 154 214 } 155 215 TRACE('D') 156 BOP_TEARDOWN(lst, ui,listedItems, NumNodes-1);216 BOP_TEARDOWN(lst, listedItems, NumNodes-1); 157 217 TRACE('d') 218 219 privateOpsCompleted += NumNodes; 158 220 159 221 bobs_prog_rollover_flag = 1; … … 161 223 bobs_prog_inserting = 0; 162 224 bobs_prog_removing = 0; 163 bobs_ops_completed += NumNodes;225 bobs_ops_completed = privateOpsCompleted; 164 226 TRACE('f') 165 227 bobs_prog_rollover_flag = 0; 166 228 TRACE('g') 167 229 } 230 #ifndef DISABLE_CLOCK_RECHECK 168 231 clock_t end = clock(); 169 232 elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC); 170 } 233 #endif 234 } 235 #ifdef DISABLE_CLOCK_RECHECK 236 { 237 clock_t end = clock(); 238 elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC); 239 } 240 #endif 171 241 172 242 double mean_op_dur_ns = elapsed_sec / ((double)bobs_ops_completed) * 1000 * 1000 * 1000; … … 175 245 free(ui); 176 246 free(listedItems); 247 free(insertOrdShuf); 177 248 } -
doc/theses/mike_brooks_MMath/benchmarks/list/observation.c
ra50fdfb r6e1e2d0 24 24 } 25 25 26 #ifdef BOBS_SHOW_ADDRESSES 27 #define SNAP \ 28 void * userAddr = bobs_getCurrentLoc(); \ 29 int userValue = bobs_getCurrentVal(); 30 #define SHOW(pfx, sfx) \ 31 printf(" " pfx "%d@%p" sfx, userValue, userAddr); 32 #else 33 #define SNAP \ 34 int userValue = bobs_getCurrentVal(); 35 #define SHOW(pfx, sfx) \ 36 printf(" " pfx "%d" sfx, userValue); 37 #endif 26 38 27 39 static void printPreds(unsigned int leash) { … … 32 44 return; 33 45 } 34 int userValue = bobs_getCurrent();46 SNAP 35 47 bobs_movePrev(); 36 48 printPreds(leash - 1); 37 printf(" %d", userValue);49 SHOW("", "") 38 50 } 39 51 static void printSuccs(unsigned int leash) { … … 44 56 return; 45 57 } 46 int userValue = bobs_getCurrent();47 printf(" %d", userValue);58 SNAP 59 SHOW("", "") 48 60 bobs_moveNext(); 49 61 printSuccs(leash - 1); … … 59 71 60 72 bobs_seek(here); 61 int userValue = bobs_getCurrent();62 printf(" <%d>", userValue);73 SNAP 74 SHOW("<", ">") 63 75 64 76 bobs_moveNext(); -
doc/theses/mike_brooks_MMath/benchmarks/list/observation.h
ra50fdfb r6e1e2d0 8 8 extern enum bobs_op_polarity_t { insfirst, inslast } bobs_op_polarity; 9 9 10 void bobs_seek(unsigned int); 11 void bobs_moveNext(); 12 void bobs_movePrev(); 13 int bobs_hasCurrent(); 14 int bobs_getCurrent(); 10 void bobs_seek(unsigned int); 11 void bobs_moveNext(); 12 void bobs_movePrev(); 13 int bobs_hasCurrent(); 14 void * bobs_getCurrentLoc(); 15 int bobs_getCurrentVal(); 15 16 16 17 extern volatile size_t bobs_ops_completed; -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-allhead.h
ra50fdfb r6e1e2d0 3 3 // allhead: inserts and removes happen via the api-provided "last"/"tail"/"back"/"first"/"tail"/"front" 4 4 5 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i])6 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_LAST(B_UserItem, lst)5 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item)) 6 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_LAST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-inselem.h
ra50fdfb r6e1e2d0 3 3 // inselem: inserts happen via an element-level operation and removes happen via the api-provided "last"/"tail"/"back" 4 4 5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i])5 #define BOP_INIT(lst, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item)) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_BEFORE(B_UserItem, lst, ui[i], iters[i-1])8 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_LAST(B_UserItem, lst)7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_BEFORE(B_UserItem, lst, (item), iters[(insNo)-1]) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_LAST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-remelem.h
ra50fdfb r6e1e2d0 3 3 // remelem: removes happen via an element-level operation and inserts happen via the api-provided "first"/"head"/"front" 4 4 5 #define BOP_TEARDOWN(lst, ui, iters, i)BFX_REMOVE_LAST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, iters, remNo) BFX_REMOVE_LAST(B_UserItem, lst) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i])8 #define BOP_REMOVE(lst, ui, iters, i) BFX_REMOVE_HERE(B_UserItem, lst, iters[i])7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item)) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_HERE(B_UserItem, lst, iters[(remNo)]) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-allhead.h
ra50fdfb r6e1e2d0 3 3 // allhead: inserts and removes happen via the api-provided "last"/"tail"/"back"/"first"/"tail"/"front" 4 4 5 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i])6 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_FIRST(B_UserItem, lst)5 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item)) 6 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_FIRST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-inselem.h
ra50fdfb r6e1e2d0 3 3 // inselem: inserts happen via an element-level operation and removes happen via the api-provided "first"/"tail"/"front" 4 4 5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i])5 #define BOP_INIT(lst, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item)) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_AFTER(B_UserItem, lst, ui[i], iters[i-1])8 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_FIRST(B_UserItem, lst)7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_AFTER(B_UserItem, lst, (item), iters[(insNo)-1]) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_FIRST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-remelem.h
ra50fdfb r6e1e2d0 3 3 // remelem: removes happen via an element-level operation and inserts happen via the api-provided "last"/"tail"/"back" 4 4 5 #define BOP_TEARDOWN(lst, ui, iters, i)BFX_REMOVE_FIRST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, iters, remNo) BFX_REMOVE_FIRST(B_UserItem, lst) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i])8 #define BOP_REMOVE(lst, ui, iters, i) BFX_REMOVE_HERE(B_UserItem, lst, iters[i])7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item)) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_HERE(B_UserItem, lst, iters[(remNo)]) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-allhead.h
ra50fdfb r6e1e2d0 3 3 // allhead: inserts and removes happen via the api-provided "first"/"head"/"front" 4 4 5 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i])6 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_FIRST(B_UserItem, lst)5 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item)) 6 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_FIRST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-inselem.h
ra50fdfb r6e1e2d0 3 3 // inselem: inserts happen via an element-level operation and removes happen via the api-provided "first"/"head"/"front" 4 4 5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i])5 #define BOP_INIT(lst, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item)) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_BEFORE(B_UserItem, lst, ui[i], iters[i-1])8 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_FIRST(B_UserItem, lst)7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_BEFORE(B_UserItem, lst, (item), iters[insNo-1]) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_FIRST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-remelem.h
ra50fdfb r6e1e2d0 3 3 // remelem: removes happen via an element-level operation and inserts happen via the api-provided "first"/"head"/"front" 4 4 5 #define BOP_TEARDOWN(lst, ui, iters, i)BFX_REMOVE_FIRST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, iters, remNo) BFX_REMOVE_FIRST(B_UserItem, lst) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i])8 #define BOP_REMOVE(lst, ui, iters, i) BFX_REMOVE_HERE(B_UserItem, lst, iters[NumNodes-(i)-1])7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item)) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_HERE(B_UserItem, lst, iters[NumNodes-(remNo)-1]) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-allhead.h
ra50fdfb r6e1e2d0 3 3 // allhead: inserts and removes happen via the api-provided "last"/"tail"/"back" 4 4 5 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i])6 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_LAST(B_UserItem, lst)5 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item)) 6 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_LAST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-inselem.h
ra50fdfb r6e1e2d0 3 3 // inselem: inserts happen via an element-level operation and removes happen via the api-provided "last"/"tail"/"back" 4 4 5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i])5 #define BOP_INIT(lst, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item)) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_AFTER(B_UserItem, lst, ui[i], iters[i-1])8 #define BOP_REMOVE(lst, ui, iters, i)BFX_REMOVE_LAST(B_UserItem, lst)7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_AFTER(B_UserItem, lst, (item), iters[(insNo)-1]) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_LAST(B_UserItem, lst) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-remelem.h
ra50fdfb r6e1e2d0 3 3 // remelem: removes happen via an element-level operation and inserts happen via the api-provided "last"/"tail"/"back" 4 4 5 #define BOP_TEARDOWN(lst, ui, iters, i)BFX_REMOVE_LAST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, iters, remNo) BFX_REMOVE_LAST(B_UserItem, lst) 6 6 7 #define BOP_INSERT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i])8 #define BOP_REMOVE(lst, ui, iters, i) BFX_REMOVE_HERE(B_UserItem, lst, iters[NumNodes-(i)-1])7 #define BOP_INSERT(lst, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item)) 8 #define BOP_REMOVE(lst, iters, remNo) BFX_REMOVE_HERE(B_UserItem, lst, iters[NumNodes-(remNo)-1]) -
doc/theses/mike_brooks_MMath/benchmarks/list/results-baseline.csv
ra50fdfb r6e1e2d0 1 2023-04-03 15:39:25,5,./perfexp--lq-tailq--stack-insfirst-inselem,443000000,5.005379,11.298824 2 2023-04-03 15:39:30,3,./perfexp--lq-tailq--queue-inslast-allhead,570000000,5.007309,8.784753 3 2023-04-03 15:39:35,3,./perfexp--lq-tailq--stack-inslast-inselem,606000000,5.000877,8.252272 4 2023-04-03 15:39:40,2,./perfexp--upp-upp--stack-insfirst-remelem,657000000,5.006698,7.620545 5 2023-04-03 15:39:45,1,./perfexp--lq-tailq--stack-inslast-allhead,617000000,5.002409,8.107632 6 2023-04-03 15:39:50,2,./perfexp--lq-tailq--stack-inslast-inselem,607000000,5.007467,8.249534 7 2023-04-03 15:39:55,3,./perfexp--upp-upp--stack-inslast-allhead,572000000,5.002847,8.746236 8 2023-04-03 15:40:01,5,./perfexp--lq-tailq--queue-insfirst-allhead,536000000,5.000997,9.330218 9 2023-04-03 15:40:06,5,./perfexp--upp-upp--queue-insfirst-allhead,458000000,5.009543,10.937867 10 2023-04-03 15:40:11,5,./perfexp--cfa-cfa--queue-inslast-remelem,710000000,5.003976,7.047854 11 2023-04-03 15:40:16,1,./perfexp--cpp-stlref--stack-inslast-allhead,166000000,5.002189,30.133669 12 2023-04-03 15:40:21,2,./perfexp--cfa-cfa--stack-inslast-allhead,547000000,5.004804,9.149550 13 2023-04-03 15:40:26,1,./perfexp--lq-tailq--stack-insfirst-remelem,713000000,5.006425,7.021634 14 2023-04-03 15:40:31,4,./perfexp--upp-upp--stack-inslast-allhead,567000000,5.003325,8.824206 15 2023-04-03 15:40:36,2,./perfexp--upp-upp--stack-inslast-inselem,489000000,5.000271,10.225503 16 2023-04-03 15:40:41,2,./perfexp--cpp-stlref--stack-inslast-remelem,158000000,5.017243,31.754703 17 2023-04-03 15:40:46,5,./perfexp--upp-upp--stack-inslast-allhead,549000000,5.005594,9.117658 18 2023-04-03 15:40:51,3,./perfexp--upp-upp--queue-inslast-inselem,487000000,5.003425,10.273973 19 2023-04-03 15:40:56,4,./perfexp--cfa-cfa--stack-inslast-inselem,538000000,5.004632,9.302290 20 2023-04-03 15:41:01,3,./perfexp--cfa-cfa--queue-insfirst-remelem,718000000,5.006064,6.972234 21 2023-04-03 15:41:06,3,./perfexp--cpp-stlref--queue-inslast-inselem,167000000,5.027628,30.105557 22 2023-04-03 15:41:11,5,./perfexp--cfa-cfa--queue-insfirst-allhead,510000000,5.007280,9.818196 23 2023-04-03 15:41:16,5,./perfexp--lq-list--stack-insfirst-inselem,462000000,5.010782,10.845848 24 2023-04-03 15:41:21,5,./perfexp--lq-tailq--queue-inslast-allhead,565000000,5.008089,8.863874 25 2023-04-03 15:41:26,2,./perfexp--cpp-stlref--queue-insfirst-inselem,167000000,5.002444,29.954754 26 2023-04-03 15:41:31,3,./perfexp--cpp-stlref--queue-insfirst-allhead,172000000,5.012068,29.139930 27 2023-04-03 15:41:36,2,./perfexp--upp-upp--queue-insfirst-inselem,465000000,5.003175,10.759516 28 2023-04-03 15:41:41,4,./perfexp--lq-tailq--queue-inslast-remelem,535000000,5.003059,9.351512 29 2023-04-03 15:41:46,4,./perfexp--cpp-stlref--queue-inslast-remelem,166000000,5.000510,30.123554 30 2023-04-03 15:41:51,3,./perfexp--lq-tailq--stack-insfirst-remelem,710000000,5.003302,7.046904 31 2023-04-03 15:41:56,1,./perfexp--lq-tailq--queue-insfirst-allhead,539000000,5.005817,9.287230 32 2023-04-03 15:42:01,5,./perfexp--upp-upp--queue-insfirst-remelem,608000000,5.006322,8.234082 33 2023-04-03 15:42:06,2,./perfexp--cpp-stlref--stack-insfirst-inselem,165000000,5.002635,30.319000 34 2023-04-03 15:42:11,5,./perfexp--cfa-cfa--queue-insfirst-inselem,510000000,5.009883,9.823300 35 2023-04-03 15:42:16,1,./perfexp--cfa-cfa--stack-insfirst-allhead,552000000,5.000119,9.058187 36 2023-04-03 15:42:21,1,./perfexp--lq-list--stack-insfirst-remelem,712000000,5.005641,7.030395 37 2023-04-03 15:42:26,3,./perfexp--upp-upp--stack-inslast-remelem,685000000,5.000472,7.299959 38 2023-04-03 15:42:31,1,./perfexp--lq-tailq--stack-insfirst-inselem,444000000,5.008487,11.280376 39 2023-04-03 15:42:37,2,./perfexp--cpp-stlref--stack-inslast-allhead,161000000,5.025004,31.211205 40 2023-04-03 15:42:42,3,./perfexp--cfa-cfa--stack-inslast-allhead,545000000,5.002831,9.179506 41 2023-04-03 15:42:47,1,./perfexp--upp-upp--stack-inslast-allhead,567000000,5.007839,8.832168 42 2023-04-03 15:42:52,5,./perfexp--cpp-stlref--stack-insfirst-inselem,165000000,5.025721,30.458915 43 2023-04-03 15:42:57,3,./perfexp--lq-tailq--queue-insfirst-allhead,537000000,5.005007,9.320311 44 2023-04-03 15:43:02,5,./perfexp--cfa-cfa--stack-insfirst-remelem,759000000,5.000831,6.588710 45 2023-04-03 15:43:07,4,./perfexp--cpp-stlref--queue-insfirst-remelem,170000000,5.016844,29.510847 46 2023-04-03 15:43:12,2,./perfexp--upp-upp--queue-insfirst-remelem,664000000,5.002228,7.533476 47 2023-04-03 15:43:17,4,./perfexp--lq-tailq--queue-insfirst-allhead,537000000,5.005068,9.320425 48 2023-04-03 15:43:22,3,./perfexp--lq-tailq--stack-insfirst-inselem,444000000,5.009009,11.281552 49 2023-04-03 15:43:27,5,./perfexp--cfa-cfa--stack-inslast-inselem,538000000,5.000494,9.294599 50 2023-04-03 15:43:32,3,./perfexp--cpp-stlref--stack-insfirst-inselem,166000000,5.023027,30.259199 51 2023-04-03 15:43:37,2,./perfexp--cpp-stlref--queue-insfirst-allhead,168000000,5.019833,29.879958 52 2023-04-03 15:43:42,1,./perfexp--upp-upp--stack-inslast-inselem,491000000,5.000784,10.184896 53 2023-04-03 15:43:47,3,./perfexp--cpp-stlref--stack-inslast-remelem,159000000,5.025671,31.607994 54 2023-04-03 15:43:52,1,./perfexp--cfa-cfa--stack-inslast-remelem,768000000,5.003314,6.514732 55 2023-04-03 15:43:57,5,./perfexp--cfa-cfa--queue-insfirst-remelem,718000000,5.000123,6.963960 56 2023-04-03 15:44:02,4,./perfexp--cfa-cfa--queue-inslast-remelem,706000000,5.005028,7.089275 57 2023-04-03 15:44:07,1,./perfexp--lq-tailq--stack-insfirst-allhead,594000000,5.002014,8.420899 58 2023-04-03 15:44:12,3,./perfexp--lq-tailq--queue-insfirst-inselem,437000000,5.006085,11.455572 59 2023-04-03 15:44:17,2,./perfexp--lq-tailq--stack-inslast-remelem,826000000,5.000880,6.054334 60 2023-04-03 15:44:22,3,./perfexp--upp-upp--stack-inslast-inselem,492000000,5.009566,10.182045 61 2023-04-03 15:44:27,2,./perfexp--upp-upp--stack-inslast-remelem,697000000,5.000839,7.174805 62 2023-04-03 15:44:32,2,./perfexp--cfa-cfa--stack-insfirst-remelem,756000000,5.000070,6.613849 63 2023-04-03 15:44:37,5,./perfexp--lq-tailq--stack-insfirst-remelem,717000000,5.007000,6.983264 64 2023-04-03 15:44:43,4,./perfexp--cfa-cfa--queue-insfirst-inselem,507000000,5.000763,9.863438 65 2023-04-03 15:44:48,1,./perfexp--cpp-stlref--queue-inslast-inselem,161000000,5.027524,31.226857 66 2023-04-03 15:44:53,4,./perfexp--cfa-cfa--queue-insfirst-allhead,508000000,5.009748,9.861709 67 2023-04-03 15:44:58,2,./perfexp--lq-tailq--stack-insfirst-allhead,595000000,5.001977,8.406684 68 2023-04-03 15:45:03,4,./perfexp--lq-tailq--queue-insfirst-inselem,431000000,5.000710,11.602575 69 2023-04-03 15:45:08,3,./perfexp--upp-upp--stack-insfirst-allhead,601000000,5.002087,8.322940 70 2023-04-03 15:45:13,5,./perfexp--lq-tailq--stack-inslast-remelem,828000000,5.002858,6.042099 71 2023-04-03 15:45:18,4,./perfexp--upp-upp--stack-insfirst-allhead,520000000,5.008182,9.631119 72 2023-04-03 15:45:23,5,./perfexp--lq-tailq--queue-inslast-remelem,529000000,5.000836,9.453376 73 2023-04-03 15:45:28,4,./perfexp--cfa-cfa--queue-insfirst-remelem,718000000,5.002385,6.967110 74 2023-04-03 15:45:33,4,./perfexp--cpp-stlref--stack-inslast-allhead,162000000,5.021934,30.999593 75 2023-04-03 15:45:38,5,./perfexp--cpp-stlref--stack-inslast-inselem,160000000,5.015857,31.349106 76 2023-04-03 15:45:43,3,./perfexp--cfa-cfa--stack-inslast-inselem,539000000,5.008154,9.291566 77 2023-04-03 15:45:48,3,./perfexp--cpp-stlref--stack-inslast-inselem,163000000,5.010634,30.740086 78 2023-04-03 15:45:53,5,./perfexp--cpp-stlref--stack-insfirst-allhead,166000000,5.018746,30.233410 79 2023-04-03 15:45:58,1,./perfexp--cfa-cfa--queue-inslast-remelem,710000000,5.006924,7.052006 80 2023-04-03 15:46:03,1,./perfexp--cpp-stlref--stack-inslast-remelem,156000000,5.000411,32.053917 81 2023-04-03 15:46:08,2,./perfexp--lq-tailq--stack-inslast-allhead,617000000,5.005184,8.112130 82 2023-04-03 15:46:13,1,./perfexp--cfa-cfa--queue-insfirst-remelem,719000000,5.003622,6.959140 83 2023-04-03 15:46:18,4,./perfexp--lq-tailq--queue-inslast-allhead,564000000,5.000835,8.866729 84 2023-04-03 15:46:23,1,./perfexp--lq-tailq--queue-insfirst-remelem,759000000,5.001690,6.589842 85 2023-04-03 15:46:28,3,./perfexp--cpp-stlref--queue-insfirst-remelem,169000000,5.025107,29.734361 86 2023-04-03 15:46:33,1,./perfexp--cpp-stlref--stack-insfirst-allhead,166000000,5.027112,30.283807 87 2023-04-03 15:46:38,1,./perfexp--cpp-stlref--queue-insfirst-remelem,169000000,5.006199,29.622479 88 2023-04-03 15:46:44,2,./perfexp--upp-upp--stack-inslast-allhead,566000000,5.000864,8.835449 89 2023-04-03 15:46:49,2,./perfexp--cfa-cfa--queue-inslast-allhead,517000000,5.009262,9.689095 90 2023-04-03 15:46:54,2,./perfexp--lq-tailq--stack-insfirst-inselem,445000000,5.000014,11.235987 91 2023-04-03 15:46:59,3,./perfexp--lq-list--stack-insfirst-remelem,713000000,5.003234,7.017158 92 2023-04-03 15:47:04,3,./perfexp--lq-tailq--queue-insfirst-remelem,759000000,5.001448,6.589523 93 2023-04-03 15:47:09,4,./perfexp--cpp-stlref--stack-inslast-inselem,164000000,5.002294,30.501793 94 2023-04-03 15:47:14,3,./perfexp--cpp-stlref--stack-insfirst-allhead,166000000,5.015560,30.214217 95 2023-04-03 15:47:19,2,./perfexp--lq-tailq--queue-inslast-remelem,533000000,5.003926,9.388229 96 2023-04-03 15:47:24,2,./perfexp--cpp-stlref--stack-inslast-inselem,164000000,5.013968,30.572976 97 2023-04-03 15:47:29,3,./perfexp--lq-tailq--stack-inslast-remelem,833000000,5.003961,6.007156 98 2023-04-03 15:47:34,2,./perfexp--cfa-cfa--stack-insfirst-allhead,552000000,5.005105,9.067219 99 2023-04-03 15:47:39,5,./perfexp--upp-upp--queue-inslast-allhead,539000000,5.003768,9.283429 100 2023-04-03 15:47:44,2,./perfexp--cpp-stlref--queue-inslast-remelem,163000000,5.022589,30.813429 101 2023-04-03 15:47:49,5,./perfexp--cpp-stlref--queue-inslast-inselem,165000000,5.027219,30.467994 102 2023-04-03 15:47:54,5,./perfexp--cpp-stlref--queue-inslast-allhead,170000000,5.024832,29.557835 103 2023-04-03 15:47:59,3,./perfexp--cpp-stlref--queue-inslast-remelem,165000000,5.027366,30.468885 104 2023-04-03 15:48:04,1,./perfexp--cfa-cfa--stack-inslast-inselem,536000000,5.005369,9.338375 105 2023-04-03 15:48:09,1,./perfexp--cpp-stlref--queue-inslast-remelem,162000000,5.023907,31.011772 106 2023-04-03 15:48:14,4,./perfexp--cpp-stlref--stack-insfirst-inselem,165000000,5.002599,30.318782 107 2023-04-03 15:48:19,4,./perfexp--cfa-cfa--queue-inslast-inselem,519000000,5.007842,9.649021 108 2023-04-03 15:48:24,4,./perfexp--cpp-stlref--queue-insfirst-inselem,170000000,5.028952,29.582071 109 2023-04-03 15:48:29,1,./perfexp--lq-tailq--queue-insfirst-inselem,433000000,5.010306,11.571145 110 2023-04-03 15:48:34,2,./perfexp--cfa-cfa--queue-inslast-remelem,709000000,5.006604,7.061501 111 2023-04-03 15:48:39,4,./perfexp--upp-upp--stack-inslast-inselem,491000000,5.004649,10.192768 112 2023-04-03 15:48:44,4,./perfexp--lq-tailq--stack-inslast-inselem,606000000,5.003287,8.256249 113 2023-04-03 15:48:49,5,./perfexp--lq-tailq--queue-inslast-inselem,557000000,5.007731,8.990540 114 2023-04-03 15:48:54,4,./perfexp--upp-upp--queue-insfirst-inselem,460000000,5.002636,10.875296 115 2023-04-03 15:48:59,4,./perfexp--upp-upp--queue-inslast-allhead,537000000,5.005155,9.320587 116 2023-04-03 15:49:04,2,./perfexp--upp-upp--queue-inslast-allhead,538000000,5.007986,9.308524 117 2023-04-03 15:49:10,5,./perfexp--upp-upp--stack-insfirst-inselem,526000000,5.007934,9.520787 118 2023-04-03 15:49:15,5,./perfexp--cpp-stlref--stack-inslast-allhead,165000000,5.014335,30.389909 119 2023-04-03 15:49:20,5,./perfexp--cpp-stlref--stack-insfirst-remelem,156000000,5.013451,32.137506 120 2023-04-03 15:49:25,3,./perfexp--cfa-cfa--stack-insfirst-inselem,548000000,5.000615,9.125210 121 2023-04-03 15:49:30,4,./perfexp--cfa-cfa--stack-inslast-remelem,769000000,5.001464,6.503854 122 2023-04-03 15:49:35,1,./perfexp--upp-upp--queue-inslast-remelem,603000000,5.003718,8.298040 123 2023-04-03 15:49:40,2,./perfexp--cpp-stlref--queue-inslast-inselem,164000000,5.012683,30.565140 124 2023-04-03 15:49:45,5,./perfexp--upp-upp--stack-insfirst-remelem,642000000,5.004144,7.794617 125 2023-04-03 15:49:50,4,./perfexp--upp-upp--queue-inslast-remelem,606000000,5.001222,8.252842 126 2023-04-03 15:49:55,2,./perfexp--cpp-stlref--stack-insfirst-remelem,158000000,5.016260,31.748481 127 2023-04-03 15:50:00,5,./perfexp--cfa-cfa--queue-inslast-allhead,518000000,5.003133,9.658558 128 2023-04-03 15:50:05,2,./perfexp--upp-upp--queue-inslast-remelem,610000000,5.003194,8.201957 129 2023-04-03 15:50:10,4,./perfexp--lq-tailq--stack-inslast-remelem,829000000,5.004086,6.036292 130 2023-04-03 15:50:15,5,./perfexp--lq-tailq--stack-insfirst-allhead,596000000,5.008331,8.403240 131 2023-04-03 15:50:20,3,./perfexp--cpp-stlref--stack-insfirst-remelem,157000000,5.028128,32.026293 132 2023-04-03 15:50:25,1,./perfexp--cfa-cfa--stack-inslast-allhead,545000000,5.003736,9.181167 133 2023-04-03 15:50:30,2,./perfexp--cpp-stlref--stack-insfirst-allhead,166000000,5.011507,30.189801 134 2023-04-03 15:50:35,2,./perfexp--lq-list--stack-insfirst-inselem,441000000,5.004092,11.347147 135 2023-04-03 15:50:40,1,./perfexp--lq-tailq--stack-inslast-remelem,831000000,5.002214,6.019511 136 2023-04-03 15:50:45,2,./perfexp--cfa-cfa--stack-insfirst-inselem,549000000,5.006757,9.119776 137 2023-04-03 15:50:51,4,./perfexp--upp-upp--stack-inslast-remelem,707000000,5.000598,7.072982 138 2023-04-03 15:50:56,2,./perfexp--cfa-cfa--queue-inslast-inselem,519000000,5.000666,9.635195 139 2023-04-03 15:51:01,4,./perfexp--lq-tailq--stack-insfirst-remelem,715000000,5.002704,6.996789 140 2023-04-03 15:51:06,3,./perfexp--cfa-cfa--stack-inslast-remelem,772000000,5.003203,6.480833 141 2023-04-03 15:51:11,1,./perfexp--upp-upp--stack-insfirst-inselem,524000000,5.006068,9.553565 142 2023-04-03 15:51:16,2,./perfexp--upp-upp--queue-insfirst-allhead,510000000,5.009613,9.822771 143 2023-04-03 15:51:21,3,./perfexp--lq-tailq--queue-inslast-remelem,530000000,5.006810,9.446811 144 2023-04-03 15:51:26,4,./perfexp--cpp-stlref--stack-insfirst-remelem,159000000,5.007889,31.496157 145 2023-04-03 15:51:31,4,./perfexp--upp-upp--queue-insfirst-remelem,661000000,5.002903,7.568688 146 2023-04-03 15:51:36,2,./perfexp--lq-tailq--queue-insfirst-inselem,432000000,5.003819,11.582914 147 2023-04-03 15:51:41,1,./perfexp--upp-upp--stack-insfirst-remelem,655000000,5.007278,7.644699 148 2023-04-03 15:51:46,3,./perfexp--lq-tailq--stack-insfirst-allhead,596000000,5.002249,8.393035 149 2023-04-03 15:51:51,5,./perfexp--upp-upp--stack-inslast-inselem,493000000,5.008268,10.158759 150 2023-04-03 15:51:56,5,./perfexp--cfa-cfa--queue-inslast-inselem,520000000,5.008160,9.631077 151 2023-04-03 15:52:01,2,./perfexp--cfa-cfa--queue-insfirst-allhead,509000000,5.001747,9.826615 152 2023-04-03 15:52:06,2,./perfexp--cfa-cfa--queue-insfirst-remelem,717000000,5.003431,6.978286 153 2023-04-03 15:52:11,5,./perfexp--cfa-cfa--stack-insfirst-inselem,548000000,5.005236,9.133642 154 2023-04-03 15:52:16,5,./perfexp--upp-upp--stack-insfirst-allhead,589000000,5.008330,8.503107 155 2023-04-03 15:52:21,3,./perfexp--upp-upp--queue-inslast-remelem,606000000,5.000791,8.252130 156 2023-04-03 15:52:26,2,./perfexp--cfa-cfa--queue-insfirst-inselem,509000000,5.005662,9.834306 157 2023-04-03 15:52:31,2,./perfexp--cpp-stlref--queue-insfirst-remelem,170000000,5.014890,29.499353 158 2023-04-03 15:52:36,4,./perfexp--upp-upp--stack-insfirst-inselem,526000000,5.008703,9.522249 159 2023-04-03 15:52:42,3,./perfexp--lq-list--stack-insfirst-inselem,442000000,5.009383,11.333446 160 2023-04-03 15:52:47,3,./perfexp--cfa-cfa--queue-inslast-inselem,520000000,5.007789,9.630363 161 2023-04-03 15:52:52,5,./perfexp--cpp-stlref--queue-insfirst-inselem,167000000,5.011863,30.011156 162 2023-04-03 15:52:57,3,./perfexp--cfa-cfa--stack-insfirst-remelem,761000000,5.004427,6.576120 163 2023-04-03 15:53:02,1,./perfexp--lq-tailq--queue-inslast-allhead,569000000,5.000007,8.787359 164 2023-04-03 15:53:07,4,./perfexp--cfa-cfa--stack-insfirst-remelem,755000000,5.006075,6.630563 165 2023-04-03 15:53:12,1,./perfexp--cfa-cfa--queue-insfirst-allhead,508000000,5.007775,9.857825 166 2023-04-03 15:53:17,3,./perfexp--upp-upp--queue-insfirst-remelem,662000000,5.003549,7.558231 167 2023-04-03 15:53:22,1,./perfexp--upp-upp--stack-insfirst-allhead,602000000,5.003572,8.311581 168 2023-04-03 15:53:27,5,./perfexp--lq-tailq--stack-inslast-allhead,617000000,5.001483,8.106131 169 2023-04-03 15:53:32,4,./perfexp--lq-list--stack-insfirst-inselem,442000000,5.010176,11.335240 170 2023-04-03 15:53:37,4,./perfexp--cpp-stlref--stack-insfirst-allhead,166000000,5.013545,30.202078 171 2023-04-03 15:53:42,5,./perfexp--cfa-cfa--stack-insfirst-allhead,552000000,5.000744,9.059319 172 2023-04-03 15:53:47,4,./perfexp--lq-tailq--queue-insfirst-remelem,765000000,5.002711,6.539492 173 2023-04-03 15:53:52,3,./perfexp--cfa-cfa--stack-insfirst-allhead,552000000,5.007654,9.071837 174 2023-04-03 15:53:57,1,./perfexp--upp-upp--queue-insfirst-remelem,660000000,5.001139,7.577483 175 2023-04-03 15:54:02,3,./perfexp--cpp-stlref--queue-insfirst-inselem,169000000,5.013091,29.663260 176 2023-04-03 15:54:07,2,./perfexp--lq-list--stack-insfirst-remelem,713000000,5.006786,7.022140 177 2023-04-03 15:54:12,1,./perfexp--lq-tailq--stack-inslast-inselem,606000000,5.002385,8.254761 178 2023-04-03 15:54:17,4,./perfexp--upp-upp--queue-inslast-inselem,487000000,5.003862,10.274871 179 2023-04-03 15:54:22,1,./perfexp--lq-list--stack-insfirst-allhead,593000000,5.002939,8.436659 180 2023-04-03 15:54:27,2,./perfexp--lq-tailq--queue-inslast-allhead,565000000,5.004251,8.857081 181 2023-04-03 15:54:32,5,./perfexp--lq-list--stack-insfirst-allhead,592000000,5.001007,8.447647 182 2023-04-03 15:54:37,3,./perfexp--upp-upp--queue-inslast-allhead,538000000,5.007986,9.308524 183 2023-04-03 15:54:42,4,./perfexp--lq-tailq--stack-inslast-allhead,617000000,5.004785,8.111483 184 2023-04-03 15:54:47,2,./perfexp--lq-tailq--queue-insfirst-allhead,537000000,5.000866,9.312600 185 2023-04-03 15:54:52,3,./perfexp--lq-tailq--stack-inslast-allhead,593000000,5.001259,8.433826 186 2023-04-03 15:54:57,5,./perfexp--lq-tailq--stack-inslast-inselem,607000000,5.008090,8.250560 187 2023-04-03 15:55:02,1,./perfexp--cfa-cfa--queue-inslast-inselem,520000000,5.007405,9.629625 188 2023-04-03 15:55:07,2,./perfexp--lq-list--stack-insfirst-allhead,590000000,5.000838,8.475997 189 2023-04-03 15:55:12,3,./perfexp--upp-upp--stack-insfirst-inselem,525000000,5.004319,9.532036 190 2023-04-03 15:55:17,5,./perfexp--cpp-stlref--queue-insfirst-remelem,170000000,5.018299,29.519406 191 2023-04-03 15:55:22,3,./perfexp--lq-tailq--queue-inslast-inselem,557000000,5.000287,8.977176 192 2023-04-03 15:55:28,1,./perfexp--lq-tailq--queue-inslast-inselem,550000000,5.002507,9.095467 193 2023-04-03 15:55:33,4,./perfexp--lq-tailq--queue-inslast-inselem,557000000,5.002020,8.980287 194 2023-04-03 15:55:38,1,./perfexp--cfa-cfa--queue-insfirst-inselem,507000000,5.001630,9.865148 195 2023-04-03 15:55:43,1,./perfexp--cpp-stlref--stack-inslast-inselem,166000000,5.029390,30.297530 196 2023-04-03 15:55:48,2,./perfexp--upp-upp--queue-inslast-inselem,486000000,5.003020,10.294280 197 2023-04-03 15:55:53,3,./perfexp--upp-upp--queue-insfirst-inselem,461000000,5.000073,10.846145 198 2023-04-03 15:55:58,5,./perfexp--cfa-cfa--stack-inslast-allhead,547000000,5.004262,9.148559 199 2023-04-03 15:56:03,1,./perfexp--lq-tailq--queue-inslast-remelem,546000000,5.005073,9.166800 200 2023-04-03 15:56:08,3,./perfexp--lq-list--stack-insfirst-allhead,591000000,5.003465,8.466100 201 2023-04-03 15:56:13,2,./perfexp--lq-tailq--stack-insfirst-remelem,716000000,5.001052,6.984709 202 2023-04-03 15:56:18,4,./perfexp--cfa-cfa--queue-inslast-allhead,516000000,5.003638,9.696973 203 2023-04-03 15:56:23,1,./perfexp--cpp-stlref--stack-insfirst-remelem,159000000,5.008347,31.499038 204 2023-04-03 15:56:28,4,./perfexp--lq-tailq--stack-insfirst-inselem,445000000,5.007219,11.252178 205 2023-04-03 15:56:33,2,./perfexp--lq-tailq--queue-insfirst-remelem,763000000,5.000451,6.553671 206 2023-04-03 15:56:38,1,./perfexp--upp-upp--queue-insfirst-inselem,461000000,5.002222,10.850807 207 2023-04-03 15:56:43,1,./perfexp--cpp-stlref--queue-insfirst-inselem,167000000,5.019099,30.054485 208 2023-04-03 15:56:48,4,./perfexp--cfa-cfa--stack-insfirst-allhead,553000000,5.005063,9.050747 209 2023-04-03 15:56:53,2,./perfexp--lq-tailq--queue-inslast-inselem,557000000,5.001068,8.978578 210 2023-04-03 15:56:58,3,./perfexp--upp-upp--stack-insfirst-remelem,644000000,5.005232,7.772099 211 2023-04-03 15:57:03,2,./perfexp--cfa-cfa--stack-inslast-inselem,538000000,5.004795,9.302593 212 2023-04-03 15:57:08,4,./perfexp--cpp-stlref--stack-inslast-remelem,158000000,5.004902,31.676595 213 2023-04-03 15:57:13,1,./perfexp--upp-upp--queue-inslast-allhead,539000000,5.002228,9.280571 214 2023-04-03 15:57:18,5,./perfexp--cpp-stlref--stack-inslast-remelem,159000000,5.019823,31.571214 215 2023-04-03 15:57:23,1,./perfexp--upp-upp--queue-insfirst-allhead,505000000,5.008103,9.917036 216 2023-04-03 15:57:29,5,./perfexp--lq-tailq--queue-insfirst-inselem,415000000,5.000368,12.049080 217 2023-04-03 15:57:34,3,./perfexp--cfa-cfa--queue-insfirst-inselem,509000000,5.003350,9.829764 218 2023-04-03 15:57:39,1,./perfexp--upp-upp--stack-inslast-remelem,687000000,5.005699,7.286316 219 2023-04-03 15:57:44,2,./perfexp--upp-upp--stack-insfirst-inselem,526000000,5.004338,9.513951 220 2023-04-03 15:57:49,1,./perfexp--upp-upp--queue-inslast-inselem,489000000,5.001246,10.227497 221 2023-04-03 15:57:54,3,./perfexp--cfa-cfa--queue-inslast-allhead,516000000,5.004492,9.698628 222 2023-04-03 15:57:59,5,./perfexp--cfa-cfa--stack-inslast-remelem,772000000,5.002201,6.479535 223 2023-04-03 15:58:04,5,./perfexp--lq-tailq--queue-insfirst-remelem,762000000,5.002834,6.565399 224 2023-04-03 15:58:09,1,./perfexp--lq-list--stack-insfirst-inselem,441000000,5.003211,11.345150 225 2023-04-03 15:58:14,1,./perfexp--cfa-cfa--queue-inslast-allhead,516000000,5.006598,9.702709 226 2023-04-03 15:58:19,2,./perfexp--upp-upp--stack-insfirst-allhead,602000000,5.000444,8.306385 227 2023-04-03 15:58:24,3,./perfexp--cfa-cfa--queue-inslast-remelem,702000000,5.005657,7.130566 228 2023-04-03 15:58:29,4,./perfexp--cpp-stlref--queue-inslast-inselem,166000000,5.026702,30.281337 229 2023-04-03 15:58:34,4,./perfexp--upp-upp--stack-insfirst-remelem,630000000,5.005706,7.945565 230 2023-04-03 15:58:39,1,./perfexp--cfa-cfa--stack-insfirst-remelem,759000000,5.004132,6.593059 231 2023-04-03 15:58:44,5,./perfexp--cpp-stlref--queue-inslast-remelem,167000000,5.024779,30.088497 232 2023-04-03 15:58:49,5,./perfexp--upp-upp--queue-inslast-inselem,485000000,5.001876,10.313146 233 2023-04-03 15:58:54,4,./perfexp--lq-tailq--stack-insfirst-allhead,595000000,5.003147,8.408650 234 2023-04-03 15:58:59,5,./perfexp--upp-upp--stack-inslast-remelem,680000000,5.001317,7.354878 235 2023-04-03 15:59:04,5,./perfexp--upp-upp--queue-insfirst-inselem,462000000,5.006965,10.837587 236 2023-04-03 15:59:09,3,./perfexp--cpp-stlref--queue-inslast-allhead,172000000,5.023178,29.204523 237 2023-04-03 15:59:14,4,./perfexp--cpp-stlref--queue-insfirst-allhead,173000000,5.020339,29.019301 238 2023-04-03 15:59:19,5,./perfexp--lq-list--stack-insfirst-remelem,712000000,5.002571,7.026083 239 2023-04-03 15:59:24,4,./perfexp--upp-upp--queue-insfirst-allhead,506000000,5.000700,9.882806 240 2023-04-03 15:59:29,4,./perfexp--cpp-stlref--queue-inslast-allhead,167000000,5.011863,30.011156 241 2023-04-03 15:59:34,2,./perfexp--cfa-cfa--stack-inslast-remelem,771000000,5.001426,6.486934 242 2023-04-03 15:59:39,4,./perfexp--cfa-cfa--stack-insfirst-inselem,550000000,5.005721,9.101311 243 2023-04-03 15:59:44,1,./perfexp--cfa-cfa--stack-insfirst-inselem,551000000,5.002555,9.079047 244 2023-04-03 15:59:49,4,./perfexp--cfa-cfa--stack-inslast-allhead,546000000,5.001532,9.160315 245 2023-04-03 15:59:54,2,./perfexp--cpp-stlref--queue-inslast-allhead,161000000,5.006152,31.094112 246 2023-04-03 15:59:59,3,./perfexp--cpp-stlref--stack-inslast-allhead,166000000,5.020481,30.243861 247 2023-04-03 16:00:04,1,./perfexp--cpp-stlref--stack-insfirst-inselem,165000000,5.020233,30.425655 248 2023-04-03 16:00:09,3,./perfexp--cfa-cfa--queue-insfirst-allhead,509000000,5.003864,9.830774 249 2023-04-03 16:00:14,4,./perfexp--lq-list--stack-insfirst-allhead,593000000,5.002670,8.436206 250 2023-04-03 16:00:19,1,./perfexp--cpp-stlref--queue-insfirst-allhead,170000000,5.005779,29.445759 251 2023-04-03 16:00:25,1,./perfexp--cpp-stlref--queue-inslast-allhead,168000000,5.021567,29.890280 252 2023-04-03 16:00:30,5,./perfexp--cpp-stlref--queue-insfirst-allhead,170000000,5.030049,29.588524 253 2023-04-03 16:00:35,5,./perfexp--upp-upp--queue-inslast-remelem,616000000,5.007578,8.129185 254 2023-04-03 16:00:40,4,./perfexp--lq-list--stack-insfirst-remelem,713000000,5.002819,7.016576 255 2023-04-03 16:00:45,3,./perfexp--upp-upp--queue-insfirst-allhead,501000000,5.007947,9.995902 1 2023-04-06 22:38:43,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--stack-inslast-inselem,159326200,5.104060,32.035284 2 2023-04-06 22:38:48,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-remelem,224000000,5.117349,22.845308 3 2023-04-06 22:38:54,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--queue-inslast-allhead,224000000,5.062724,22.601446 4 2023-04-06 22:38:59,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-allhead,166568300,5.161427,30.986850 5 2023-04-06 22:39:04,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-remelem,169890000,5.005365,29.462387 6 2023-04-06 22:39:09,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--queue-inslast-inselem,444950000,5.003260,11.244544 7 2023-04-06 22:39:14,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--queue-insfirst-inselem,289632000,5.002701,17.272611 8 2023-04-06 22:39:19,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--queue-inslast-allhead,343938000,5.050625,14.684696 9 2023-04-06 22:39:24,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-inselem,546700000,5.031248,9.202941 10 2023-04-06 22:39:29,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--stack-inslast-allhead,177980000,5.214033,29.295612 11 2023-04-06 22:39:34,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--stack-inslast-remelem,678825000,5.007971,7.377411 12 2023-04-06 22:39:39,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--queue-inslast-remelem,177500000,5.051343,28.458270 13 2023-04-06 22:39:44,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--stack-inslast-inselem,617700000,5.012318,8.114486 14 2023-04-06 22:39:49,2,5 1000000 7 -1 2 ,./perfexp--lq-list--stack-insfirst-inselem,581000000,5.034526,8.665277 15 2023-04-06 22:39:54,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--queue-insfirst-remelem,1309000000,5.007982,3.825807 16 2023-04-06 22:39:59,3,5 100000 71 -1 3 ,./perfexp--upp-upp--stack-inslast-remelem,809400000,5.034582,6.220141 17 2023-04-06 22:40:04,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--queue-inslast-allhead,352989000,5.080867,14.393839 18 2023-04-06 22:40:10,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--stack-inslast-inselem,159326200,5.152641,32.340199 19 2023-04-06 22:40:15,4,5 100 72421 -1 4 ,./perfexp--lq-list--stack-insfirst-remelem,333136600,5.081694,15.254085 20 2023-04-06 22:40:20,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--queue-inslast-allhead,672000000,5.041239,7.501844 21 2023-04-06 22:40:25,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-remelem,159326200,5.216693,32.742217 22 2023-04-06 22:40:30,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--stack-inslast-inselem,908800000,5.036669,5.542109 23 2023-04-06 22:40:35,1,5 100 72421 -1 1 ,./perfexp--lq-list--stack-insfirst-inselem,166568300,5.225242,31.369967 24 2023-04-06 22:40:41,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--queue-inslast-allhead,137599900,5.143664,37.381306 25 2023-04-06 22:40:46,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--stack-inslast-inselem,159326200,5.104856,32.040280 26 2023-04-06 22:40:51,5,5 1000000 7 -1 5 ,./perfexp--lq-list--stack-insfirst-allhead,917000000,5.030506,5.485830 27 2023-04-06 22:40:56,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--queue-insfirst-remelem,296926100,5.105027,17.192921 28 2023-04-06 22:41:01,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-allhead,137599900,5.150764,37.432905 29 2023-04-06 22:41:06,1,5 100 72421 -1 1 ,./perfexp--lq-list--stack-insfirst-allhead,166568300,5.054932,30.347503 30 2023-04-06 22:41:11,1,5 100 72421 -1 1 ,./perfexp--upp-upp--queue-insfirst-inselem,130357800,5.100502,39.126941 31 2023-04-06 22:41:16,3,5 1000 9051 -1 3 ,./perfexp--lq-list--stack-insfirst-inselem,325836000,5.113777,15.694328 32 2023-04-06 22:41:22,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-remelem,169890000,5.046006,29.701607 33 2023-04-06 22:41:27,3,5 10000 809 -1 3 ,./perfexp--upp-upp--stack-insfirst-inselem,477310000,5.055761,10.592196 34 2023-04-06 22:41:32,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-remelem,588315000,5.001890,8.502061 35 2023-04-06 22:41:37,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-inselem,651000000,5.008924,7.694200 36 2023-04-06 22:41:42,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--stack-insfirst-remelem,590570000,5.038027,8.530787 37 2023-04-06 22:41:47,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--stack-inslast-remelem,153867000,5.210496,33.863635 38 2023-04-06 22:41:52,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--queue-insfirst-remelem,859100000,5.034777,5.860525 39 2023-04-06 22:41:57,3,5 10000 809 -1 3 ,./perfexp--lq-list--stack-insfirst-remelem,590570000,5.065984,8.578126 40 2023-04-06 22:42:02,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--stack-inslast-inselem,493490000,5.014299,10.160893 41 2023-04-06 22:42:07,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-allhead,184600000,5.079109,27.514133 42 2023-04-06 22:42:12,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-inselem,231000000,5.041959,21.826662 43 2023-04-06 22:42:17,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--stack-inslast-allhead,162918000,5.108416,31.355750 44 2023-04-06 22:42:22,4,5 100 72421 -1 4 ,./perfexp--upp-upp--queue-insfirst-remelem,260715600,5.113112,19.611838 45 2023-04-06 22:42:27,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--queue-inslast-inselem,833000000,5.028245,6.036309 46 2023-04-06 22:42:33,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--queue-inslast-inselem,352989000,5.105392,14.463318 47 2023-04-06 22:42:38,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--stack-inslast-allhead,334887000,5.039581,15.048601 48 2023-04-06 22:42:43,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--stack-insfirst-remelem,763000000,5.016755,6.575039 49 2023-04-06 22:42:48,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--stack-inslast-allhead,159326200,5.111182,32.079984 50 2023-04-06 22:42:53,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--stack-inslast-remelem,979800000,5.002241,5.105369 51 2023-04-06 22:42:58,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--stack-inslast-inselem,316785000,5.008967,15.811882 52 2023-04-06 22:43:03,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--queue-insfirst-remelem,1316000000,5.025586,3.818834 53 2023-04-06 22:43:08,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--queue-inslast-allhead,959000000,5.008021,5.222128 54 2023-04-06 22:43:13,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--stack-insfirst-remelem,461601000,5.006449,10.845837 55 2023-04-06 22:43:18,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--queue-inslast-inselem,658000000,5.029688,7.643903 56 2023-04-06 22:43:23,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--queue-inslast-inselem,658000000,5.022354,7.632757 57 2023-04-06 22:43:28,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--stack-inslast-remelem,347620800,5.032410,14.476723 58 2023-04-06 22:43:33,1,5 100 72421 -1 1 ,./perfexp--upp-upp--stack-insfirst-allhead,159326200,5.154973,32.354836 59 2023-04-06 22:43:38,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-remelem,169890000,5.130552,30.199258 60 2023-04-06 22:43:43,4,5 1000 9051 -1 4 ,./perfexp--lq-list--stack-insfirst-remelem,543060000,5.083894,9.361570 61 2023-04-06 22:43:49,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--queue-inslast-remelem,169890000,5.059665,29.782006 62 2023-04-06 22:43:54,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--stack-insfirst-allhead,910000000,5.002806,5.497589 63 2023-04-06 22:43:59,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--queue-inslast-remelem,575100000,5.010242,8.711949 64 2023-04-06 22:44:04,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--queue-insfirst-allhead,728000000,5.022596,6.899170 65 2023-04-06 22:44:09,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--stack-inslast-remelem,169890000,5.191497,30.557990 66 2023-04-06 22:44:14,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--stack-inslast-allhead,639000000,5.034492,7.878704 67 2023-04-06 22:44:19,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--queue-inslast-remelem,311410300,5.098903,16.373585 68 2023-04-06 22:44:24,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--queue-insfirst-allhead,325836000,5.135714,15.761653 69 2023-04-06 22:44:29,4,5 1000000 7 -1 4 ,./perfexp--lq-list--stack-insfirst-inselem,581000000,5.051661,8.694769 70 2023-04-06 22:44:34,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--stack-insfirst-inselem,679000000,5.043664,7.428077 71 2023-04-06 22:44:39,5,5 100 72421 -1 5 ,./perfexp--upp-upp--queue-insfirst-inselem,130357800,5.100746,39.128813 72 2023-04-06 22:44:45,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-inselem,137599900,5.151609,37.439046 73 2023-04-06 22:44:50,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--stack-inslast-allhead,672000000,5.022206,7.473521 74 2023-04-06 22:44:55,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-inselem,343938000,5.113961,14.868846 75 2023-04-06 22:45:00,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--queue-inslast-inselem,343938000,5.132823,14.923687 76 2023-04-06 22:45:05,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--queue-inslast-allhead,352989000,5.051277,14.310012 77 2023-04-06 22:45:10,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--stack-inslast-inselem,343938000,5.079431,14.768450 78 2023-04-06 22:45:15,2,5 100000 71 -1 2 ,./perfexp--upp-upp--stack-inslast-remelem,795200000,5.027511,6.322323 79 2023-04-06 22:45:20,2,5 1000 9051 -1 2 ,./perfexp--lq-list--stack-insfirst-inselem,325836000,5.097880,15.645539 80 2023-04-06 22:45:25,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--stack-inslast-allhead,325836000,5.039459,15.466244 81 2023-04-06 22:45:30,3,5 10000 809 -1 3 ,./perfexp--upp-upp--stack-inslast-inselem,444950000,5.059145,11.370143 82 2023-04-06 22:45:36,5,5 10000 809 -1 5 ,./perfexp--upp-upp--stack-inslast-inselem,444950000,5.072116,11.399294 83 2023-04-06 22:45:41,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-allhead,159326200,5.099274,32.005245 84 2023-04-06 22:45:46,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--queue-insfirst-allhead,788100000,5.037081,6.391424 85 2023-04-06 22:45:51,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--stack-inslast-allhead,1036600000,5.028854,4.851297 86 2023-04-06 22:45:56,2,5 10000 809 -1 2 ,./perfexp--upp-upp--stack-inslast-allhead,493490000,5.043056,10.219166 87 2023-04-06 22:46:01,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-remelem,169890000,5.165830,30.406910 88 2023-04-06 22:46:06,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--queue-inslast-remelem,777000000,5.026590,6.469228 89 2023-04-06 22:46:11,1,5 10000 809 -1 1 ,./perfexp--lq-list--stack-insfirst-inselem,453040000,5.042693,11.130790 90 2023-04-06 22:46:16,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--stack-inslast-inselem,159326200,5.021468,31.516901 91 2023-04-06 22:46:21,1,5 10000 809 -1 1 ,./perfexp--upp-upp--queue-insfirst-allhead,444950000,5.058905,11.369603 92 2023-04-06 22:46:26,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-inselem,159326200,5.124781,32.165338 93 2023-04-06 22:46:31,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--stack-inslast-allhead,184600000,5.086561,27.554502 94 2023-04-06 22:46:37,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-inselem,159326200,5.101698,32.020459 95 2023-04-06 22:46:42,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--queue-inslast-remelem,777000000,5.024963,6.467134 96 2023-04-06 22:46:47,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--stack-inslast-inselem,901700000,5.038805,5.588117 97 2023-04-06 22:46:52,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--stack-insfirst-allhead,325836000,5.086643,15.611053 98 2023-04-06 22:46:57,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-remelem,917000000,5.029273,5.484485 99 2023-04-06 22:47:02,2,5 100 72421 -1 2 ,./perfexp--upp-upp--stack-inslast-inselem,159326200,5.146099,32.299138 100 2023-04-06 22:47:07,5,5 100000 71 -1 5 ,./perfexp--upp-upp--stack-inslast-allhead,646100000,5.036416,7.795103 101 2023-04-06 22:47:12,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-remelem,318652400,5.011899,15.728421 102 2023-04-06 22:47:17,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-remelem,579264000,5.006702,8.643213 103 2023-04-06 22:47:22,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-inselem,477310000,5.036310,10.551445 104 2023-04-06 22:47:27,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--stack-inslast-allhead,159326200,5.051290,31.704076 105 2023-04-06 22:47:32,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--stack-inslast-allhead,509670000,5.059480,9.926972 106 2023-04-06 22:47:37,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--queue-inslast-remelem,534009000,5.021579,9.403548 107 2023-04-06 22:47:42,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-inselem,665000000,5.028019,7.560931 108 2023-04-06 22:47:47,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--stack-inslast-remelem,177500000,5.011349,28.232952 109 2023-04-06 22:47:52,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--stack-inslast-remelem,1242500000,5.025123,4.044365 110 2023-04-06 22:47:57,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--stack-inslast-allhead,325836000,5.033694,15.448551 111 2023-04-06 22:48:02,5,5 10000 809 -1 5 ,./perfexp--upp-upp--stack-insfirst-allhead,525850000,5.074913,9.650876 112 2023-04-06 22:48:08,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--queue-inslast-remelem,311410300,5.100754,16.379529 113 2023-04-06 22:48:13,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--queue-insfirst-remelem,296926100,5.107471,17.201152 114 2023-04-06 22:48:18,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-allhead,334887000,5.049385,15.077877 115 2023-04-06 22:48:23,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--stack-inslast-remelem,665000000,5.048229,7.591322 116 2023-04-06 22:48:28,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--queue-inslast-inselem,159326200,5.039389,31.629380 117 2023-04-06 22:48:33,4,5 100 72421 -1 4 ,./perfexp--upp-upp--stack-insfirst-remelem,267957700,5.032279,18.780125 118 2023-04-06 22:48:38,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-inselem,658000000,5.048589,7.672628 119 2023-04-06 22:48:43,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--stack-inslast-remelem,224000000,5.116992,22.843714 120 2023-04-06 22:48:48,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--stack-insfirst-allhead,352989000,5.129190,14.530736 121 2023-04-06 22:48:53,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--stack-inslast-remelem,224000000,5.044124,22.518411 122 2023-04-06 22:48:58,1,5 100 72421 -1 1 ,./perfexp--upp-upp--stack-inslast-allhead,159326200,5.085806,31.920714 123 2023-04-06 22:49:04,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--queue-inslast-remelem,574390000,5.067621,8.822614 124 2023-04-06 22:49:09,2,5 100 72421 -1 2 ,./perfexp--lq-list--stack-insfirst-inselem,159326200,5.003104,31.401640 125 2023-04-06 22:49:14,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--queue-insfirst-inselem,307734000,5.021786,16.318593 126 2023-04-06 22:49:19,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--queue-insfirst-inselem,973000000,5.029223,5.168780 127 2023-04-06 22:49:24,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--stack-insfirst-inselem,646100000,5.013377,7.759444 128 2023-04-06 22:49:29,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--stack-inslast-inselem,224000000,5.026205,22.438415 129 2023-04-06 22:49:34,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-allhead,162918000,5.122192,31.440307 130 2023-04-06 22:49:39,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-inselem,217000000,5.012642,23.099733 131 2023-04-06 22:49:44,1,5 1000 9051 -1 1 ,./perfexp--lq-list--stack-insfirst-remelem,534009000,5.010162,9.382168 132 2023-04-06 22:49:49,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-inselem,665000000,5.025341,7.556904 133 2023-04-06 22:49:54,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--stack-inslast-inselem,162918000,5.112699,31.382039 134 2023-04-06 22:49:59,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--queue-inslast-remelem,289684000,5.092223,17.578544 135 2023-04-06 22:50:04,1,5 10000 809 -1 1 ,./perfexp--lq-list--stack-insfirst-allhead,509670000,5.018786,9.847129 136 2023-04-06 22:50:09,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--stack-insfirst-inselem,679000000,5.046907,7.432853 137 2023-04-06 22:50:14,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--stack-inslast-allhead,763000000,5.000173,6.553307 138 2023-04-06 22:50:19,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--stack-insfirst-allhead,509670000,5.001591,9.813391 139 2023-04-06 22:50:24,1,5 100 72421 -1 1 ,./perfexp--upp-upp--queue-insfirst-remelem,260715600,5.115727,19.621868 140 2023-04-06 22:50:30,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--stack-insfirst-inselem,325836000,5.102080,15.658429 141 2023-04-06 22:50:35,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--queue-inslast-remelem,171969000,5.259251,30.582553 142 2023-04-06 22:50:40,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--queue-inslast-allhead,159326200,5.062565,31.774843 143 2023-04-06 22:50:45,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--stack-inslast-remelem,687876000,5.057051,7.351690 144 2023-04-06 22:50:50,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-inselem,159326200,5.115809,32.109025 145 2023-04-06 22:50:55,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--queue-inslast-remelem,973000000,5.015677,5.154858 146 2023-04-06 22:51:00,3,5 100 72421 -1 3 ,./perfexp--upp-upp--queue-inslast-remelem,260715600,5.002998,19.189485 147 2023-04-06 22:51:05,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--stack-insfirst-allhead,343938000,5.009464,14.565020 148 2023-04-06 22:51:10,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--stack-inslast-allhead,159326200,5.001947,31.394378 149 2023-04-06 22:51:15,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--stack-inslast-remelem,966000000,5.019736,5.196414 150 2023-04-06 22:51:20,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--queue-insfirst-allhead,461130000,5.067126,10.988498 151 2023-04-06 22:51:25,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--stack-inslast-inselem,169890000,5.037162,29.649550 152 2023-04-06 22:51:31,2,5 10000 809 -1 2 ,./perfexp--upp-upp--stack-inslast-remelem,679560000,5.044672,7.423439 153 2023-04-06 22:51:36,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-remelem,153867000,5.093303,33.101984 154 2023-04-06 22:51:41,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--stack-inslast-remelem,570213000,5.076763,8.903275 155 2023-04-06 22:51:46,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--stack-insfirst-allhead,781000000,5.034261,6.445917 156 2023-04-06 22:51:51,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--stack-insfirst-allhead,352989000,5.119857,14.504296 157 2023-04-06 22:51:56,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--queue-inslast-inselem,568000000,5.020960,8.839718 158 2023-04-06 22:52:01,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--stack-insfirst-inselem,679000000,5.020031,7.393271 159 2023-04-06 22:52:06,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--stack-inslast-inselem,477310000,5.065549,10.612702 160 2023-04-06 22:52:11,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--queue-inslast-allhead,334887000,5.061093,15.112838 161 2023-04-06 22:52:16,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-remelem,171969000,5.199554,30.235415 162 2023-04-06 22:52:21,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--stack-insfirst-remelem,791000000,5.030514,6.359689 163 2023-04-06 22:52:26,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--stack-insfirst-inselem,660300000,5.021934,7.605534 164 2023-04-06 22:52:31,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--stack-inslast-inselem,224000000,5.069797,22.633022 165 2023-04-06 22:52:37,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--queue-insfirst-inselem,766800000,5.034758,6.565934 166 2023-04-06 22:52:42,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--stack-insfirst-inselem,738400000,5.004336,6.777270 167 2023-04-06 22:52:47,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-inselem,665000000,5.024545,7.555707 168 2023-04-06 22:52:52,1,5 1000 9051 -1 1 ,./perfexp--lq-list--stack-insfirst-allhead,343938000,5.070304,14.741913 169 2023-04-06 22:52:57,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--stack-insfirst-remelem,688700000,5.007406,7.270809 170 2023-04-06 22:53:02,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-allhead,184600000,5.064279,27.433797 171 2023-04-06 22:53:07,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--stack-inslast-allhead,1078000000,5.011355,4.648752 172 2023-04-06 22:53:12,4,5 100000 71 -1 4 ,./perfexp--lq-list--stack-insfirst-allhead,809400000,5.030850,6.215530 173 2023-04-06 22:53:17,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-allhead,184600000,5.121858,27.745710 174 2023-04-06 22:53:22,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--queue-inslast-allhead,177980000,5.177338,29.089437 175 2023-04-06 22:53:27,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--queue-insfirst-inselem,298683000,5.103575,17.086928 176 2023-04-06 22:53:32,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--stack-inslast-remelem,959000000,5.004941,5.218917 177 2023-04-06 22:53:37,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--queue-inslast-inselem,453040000,5.084873,11.223894 178 2023-04-06 22:53:43,4,5 1000000 7 -1 4 ,./perfexp--lq-list--stack-insfirst-allhead,917000000,5.007210,5.460425 179 2023-04-06 22:53:48,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-allhead,485400000,5.073608,10.452427 180 2023-04-06 22:53:53,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--stack-inslast-allhead,334887000,5.007885,14.953955 181 2023-04-06 22:53:58,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-allhead,137599900,5.149462,37.423443 182 2023-04-06 22:54:03,3,5 100 72421 -1 3 ,./perfexp--upp-upp--queue-inslast-inselem,137599900,5.086708,36.967382 183 2023-04-06 22:54:08,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-inselem,343938000,5.092902,14.807616 184 2023-04-06 22:54:13,5,5 100000 71 -1 5 ,./perfexp--lq-list--stack-insfirst-remelem,688700000,5.002389,7.263524 185 2023-04-06 22:54:18,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--queue-inslast-allhead,137599900,5.146658,37.403065 186 2023-04-06 22:54:23,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--stack-inslast-remelem,597366000,5.073255,8.492708 187 2023-04-06 22:54:28,4,5 100000 71 -1 4 ,./perfexp--upp-upp--stack-insfirst-remelem,759700000,5.005199,6.588389 188 2023-04-06 22:54:33,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--stack-inslast-remelem,347620800,5.035473,14.485534 189 2023-04-06 22:54:38,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-remelem,908800000,5.019250,5.522942 190 2023-04-06 22:54:43,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-allhead,159326200,5.030282,31.572221 191 2023-04-06 22:54:48,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-allhead,177980000,5.213425,29.292196 192 2023-04-06 22:54:54,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--queue-inslast-allhead,469220000,5.071355,10.808054 193 2023-04-06 22:54:59,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--stack-insfirst-remelem,688700000,5.012374,7.278022 194 2023-04-06 22:55:04,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-remelem,720010000,5.044350,7.005944 195 2023-04-06 22:55:09,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--stack-inslast-allhead,624800000,5.034208,8.057311 196 2023-04-06 22:55:14,5,5 100 72421 -1 5 ,./perfexp--upp-upp--queue-insfirst-remelem,260715600,5.109722,19.598835 197 2023-04-06 22:55:19,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--queue-inslast-inselem,658000000,5.025521,7.637570 198 2023-04-06 22:55:24,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--queue-inslast-remelem,588315000,5.043017,8.571967 199 2023-04-06 22:55:29,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--stack-insfirst-inselem,159326200,5.003525,31.404283 200 2023-04-06 22:55:34,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-remelem,318652400,5.010231,15.723186 201 2023-04-06 22:55:39,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-inselem,137599900,5.150708,37.432498 202 2023-04-06 22:55:44,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--queue-insfirst-inselem,595000000,5.044665,8.478429 203 2023-04-06 22:55:49,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--stack-inslast-remelem,159326200,5.209063,32.694328 204 2023-04-06 22:55:55,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--stack-inslast-allhead,509670000,5.053284,9.914815 205 2023-04-06 22:56:00,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--stack-insfirst-allhead,795200000,5.012552,6.303511 206 2023-04-06 22:56:05,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--queue-insfirst-allhead,766800000,5.033161,6.563851 207 2023-04-06 22:56:10,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-allhead,159326200,5.121738,32.146238 208 2023-04-06 22:56:15,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--stack-inslast-allhead,334887000,5.028414,15.015256 209 2023-04-06 22:56:20,5,5 1000 9051 -1 5 ,./perfexp--lq-list--stack-insfirst-inselem,325836000,5.124252,15.726476 210 2023-04-06 22:56:25,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--queue-inslast-inselem,177980000,5.172291,29.061080 211 2023-04-06 22:56:30,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-remelem,830700000,5.042470,6.070146 212 2023-04-06 22:56:35,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--queue-insfirst-remelem,847000000,5.032186,5.941188 213 2023-04-06 22:56:40,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--queue-inslast-remelem,639000000,5.002609,7.828809 214 2023-04-06 22:56:45,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--queue-inslast-remelem,770000000,5.038757,6.543840 215 2023-04-06 22:56:50,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-allhead,231000000,5.137935,22.242143 216 2023-04-06 22:56:56,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--stack-inslast-allhead,224000000,5.091507,22.729942 217 2023-04-06 22:57:01,4,5 10000 809 -1 4 ,./perfexp--upp-upp--queue-insfirst-inselem,412590000,5.037820,12.210233 218 2023-04-06 22:57:06,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-remelem,231000000,5.102198,22.087437 219 2023-04-06 22:57:11,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--queue-inslast-allhead,171969000,5.164593,30.032116 220 2023-04-06 22:57:16,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--stack-inslast-remelem,169890000,5.225116,30.755877 221 2023-04-06 22:57:21,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--queue-insfirst-allhead,316785000,5.093369,16.078315 222 2023-04-06 22:57:26,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--stack-inslast-inselem,603500000,5.049990,8.367838 223 2023-04-06 22:57:31,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--queue-inslast-allhead,166568300,5.220664,31.342482 224 2023-04-06 22:57:37,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--queue-inslast-inselem,568000000,5.010944,8.822085 225 2023-04-06 22:57:42,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--queue-inslast-allhead,144842000,5.227036,36.087847 226 2023-04-06 22:57:47,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-remelem,159326200,5.217508,32.747332 227 2023-04-06 22:57:52,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-allhead,137599900,5.146662,37.403094 228 2023-04-06 22:57:57,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--stack-insfirst-remelem,667400000,5.038476,7.549410 229 2023-04-06 22:58:02,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--stack-inslast-allhead,159326200,5.013988,31.469953 230 2023-04-06 22:58:07,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-remelem,1008000000,5.010780,4.971012 231 2023-04-06 22:58:12,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--stack-inslast-remelem,1421000000,5.023422,3.535132 232 2023-04-06 22:58:17,1,5 100000 71 -1 1 ,./perfexp--upp-upp--queue-insfirst-inselem,553800000,5.060584,9.137927 233 2023-04-06 22:58:23,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--queue-insfirst-inselem,595000000,5.047132,8.482575 234 2023-04-06 22:58:28,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--queue-inslast-remelem,588315000,5.032246,8.553659 235 2023-04-06 22:58:33,5,5 100000 71 -1 5 ,./perfexp--upp-upp--stack-insfirst-allhead,724200000,5.020706,6.932762 236 2023-04-06 22:58:38,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--queue-inslast-inselem,334887000,5.003484,14.940813 237 2023-04-06 22:58:43,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--stack-insfirst-allhead,840000000,5.042287,6.002723 238 2023-04-06 22:58:48,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--queue-inslast-remelem,224000000,5.088342,22.715813 239 2023-04-06 22:58:53,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--queue-inslast-inselem,169890000,5.058348,29.774254 240 2023-04-06 22:58:58,2,5 100000 71 -1 2 ,./perfexp--upp-upp--queue-inslast-allhead,695800000,5.026595,7.224195 241 2023-04-06 22:59:03,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-inselem,184600000,5.066927,27.448142 242 2023-04-06 22:59:08,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-inselem,184600000,5.055439,27.385910 243 2023-04-06 22:59:13,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--queue-insfirst-remelem,1309000000,5.009552,3.827007 244 2023-04-06 22:59:18,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-inselem,658000000,5.048553,7.672573 245 2023-04-06 22:59:23,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--queue-inslast-allhead,137599900,5.143656,37.381248 246 2023-04-06 22:59:29,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-allhead,224000000,5.132010,22.910759 247 2023-04-06 22:59:34,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--stack-insfirst-remelem,695800000,5.046242,7.252432 248 2023-04-06 22:59:39,5,5 100000 71 -1 5 ,./perfexp--upp-upp--stack-insfirst-inselem,603500000,5.003978,8.291596 249 2023-04-06 22:59:44,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-allhead,665000000,5.025093,7.556531 250 2023-04-06 22:59:49,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-remelem,965600000,5.028275,5.207410 251 2023-04-06 22:59:54,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-remelem,687650000,5.005714,7.279450 252 2023-04-06 22:59:59,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--stack-insfirst-remelem,590570000,5.031737,8.520136 253 2023-04-06 23:00:04,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--queue-inslast-remelem,184600000,5.160974,27.957606 254 2023-04-06 23:00:09,5,5 100 72421 -1 5 ,./perfexp--lq-list--stack-insfirst-remelem,333136600,5.090510,15.280549 255 2023-04-06 23:00:14,5,5 100 72421 -1 5 ,./perfexp--lq-list--stack-insfirst-inselem,159326200,5.004048,31.407565 256 2023-04-06 23:00:19,2,5 10000 809 -1 2 ,./perfexp--upp-upp--queue-insfirst-allhead,444950000,5.073828,11.403142 257 2023-04-06 23:00:24,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--queue-inslast-allhead,224000000,5.001734,22.329170 258 2023-04-06 23:00:29,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--stack-inslast-allhead,477310000,5.050386,10.580935 259 2023-04-06 23:00:34,4,5 1000 9051 -1 4 ,./perfexp--lq-list--stack-insfirst-allhead,343938000,5.050309,14.683777 260 2023-04-06 23:00:40,3,5 10000 809 -1 3 ,./perfexp--upp-upp--queue-insfirst-allhead,444950000,5.017058,11.275555 261 2023-04-06 23:00:45,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-remelem,994000000,5.019649,5.049949 262 2023-04-06 23:00:50,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--stack-inslast-remelem,153867000,5.201021,33.802056 263 2023-04-06 23:00:55,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-remelem,1001000000,5.015588,5.010577 264 2023-04-06 23:01:00,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-remelem,161800000,5.005496,30.936316 265 2023-04-06 23:01:05,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--queue-inslast-allhead,665000000,5.035214,7.571750 266 2023-04-06 23:01:10,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--stack-inslast-allhead,159326200,5.109530,32.069616 267 2023-04-06 23:01:15,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-allhead,169890000,5.100783,30.024033 268 2023-04-06 23:01:20,1,5 100000 71 -1 1 ,./perfexp--upp-upp--stack-insfirst-remelem,639000000,5.014872,7.848000 269 2023-04-06 23:01:25,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--queue-inslast-inselem,169890000,5.046345,29.703602 270 2023-04-06 23:01:30,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--stack-insfirst-allhead,896000000,5.013958,5.595935 271 2023-04-06 23:01:35,1,5 1000000 7 -1 1 ,./perfexp--lq-list--stack-insfirst-inselem,581000000,5.047488,8.687587 272 2023-04-06 23:01:40,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--stack-insfirst-inselem,501580000,5.002330,9.973145 273 2023-04-06 23:01:45,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--stack-inslast-remelem,986900000,5.036032,5.102880 274 2023-04-06 23:01:50,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-inselem,166568300,5.162360,30.992452 275 2023-04-06 23:01:55,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--stack-inslast-inselem,325836000,5.137919,15.768420 276 2023-04-06 23:02:01,4,5 100000 71 -1 4 ,./perfexp--upp-upp--queue-insfirst-remelem,710000000,5.019927,7.070320 277 2023-04-06 23:02:06,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--stack-inslast-allhead,334887000,5.098791,15.225407 278 2023-04-06 23:02:11,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--queue-insfirst-allhead,651000000,5.049504,7.756535 279 2023-04-06 23:02:16,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--stack-insfirst-remelem,515907000,5.019478,9.729424 280 2023-04-06 23:02:21,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--stack-insfirst-allhead,325836000,5.095609,15.638570 281 2023-04-06 23:02:26,5,5 1000000 7 -1 5 ,./perfexp--lq-list--stack-insfirst-inselem,581000000,5.050648,8.693026 282 2023-04-06 23:02:31,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--stack-insfirst-remelem,534009000,5.012189,9.385964 283 2023-04-06 23:02:36,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-inselem,343938000,5.100634,14.830097 284 2023-04-06 23:02:41,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-allhead,177980000,5.039308,28.313900 285 2023-04-06 23:02:46,3,5 10000 809 -1 3 ,./perfexp--upp-upp--queue-insfirst-inselem,412590000,5.053218,12.247553 286 2023-04-06 23:02:51,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-inselem,162918000,5.104631,31.332517 287 2023-04-06 23:02:56,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-allhead,166568300,5.127294,30.781931 288 2023-04-06 23:03:02,5,5 100 72421 -1 5 ,./perfexp--upp-upp--queue-inslast-inselem,137599900,5.086178,36.963530 289 2023-04-06 23:03:07,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--queue-inslast-inselem,177500000,5.030765,28.342338 290 2023-04-06 23:03:12,4,5 1000000 7 -1 4 ,./perfexp--lq-list--stack-insfirst-remelem,798000000,5.017055,6.287036 291 2023-04-06 23:03:17,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--stack-insfirst-inselem,660300000,5.001824,7.575078 292 2023-04-06 23:03:22,4,5 10000 809 -1 4 ,./perfexp--lq-list--stack-insfirst-inselem,436860000,5.056530,11.574715 293 2023-04-06 23:03:27,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-allhead,665000000,5.023530,7.554180 294 2023-04-06 23:03:32,1,5 100000 71 -1 1 ,./perfexp--lq-list--stack-insfirst-inselem,553800000,5.027487,9.078164 295 2023-04-06 23:03:37,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--stack-inslast-allhead,672000000,5.030612,7.486030 296 2023-04-06 23:03:42,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--queue-insfirst-allhead,672000000,5.043560,7.505298 297 2023-04-06 23:03:47,2,5 100 72421 -1 2 ,./perfexp--lq-list--stack-insfirst-remelem,333136600,5.084613,15.262847 298 2023-04-06 23:03:52,3,5 100000 71 -1 3 ,./perfexp--upp-upp--stack-inslast-allhead,738400000,5.043688,6.830563 299 2023-04-06 23:03:57,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--queue-inslast-remelem,171969000,5.223951,30.377283 300 2023-04-06 23:04:02,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-inselem,162918000,5.126779,31.468463 301 2023-04-06 23:04:08,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--stack-inslast-remelem,1421000000,5.023912,3.535476 302 2023-04-06 23:04:13,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--stack-inslast-allhead,658000000,5.020341,7.629698 303 2023-04-06 23:04:18,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--stack-insfirst-remelem,461601000,5.016184,10.866926 304 2023-04-06 23:04:23,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--stack-inslast-allhead,177980000,5.210149,29.273789 305 2023-04-06 23:04:28,4,5 100 72421 -1 4 ,./perfexp--upp-upp--stack-insfirst-inselem,159326200,5.202610,32.653826 306 2023-04-06 23:04:33,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--stack-inslast-remelem,966000000,5.014821,5.191326 307 2023-04-06 23:04:38,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--stack-inslast-remelem,728100000,5.003623,6.872165 308 2023-04-06 23:04:43,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--stack-inslast-allhead,184600000,5.136308,27.823987 309 2023-04-06 23:04:48,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-allhead,477310000,5.001601,10.478727 310 2023-04-06 23:04:53,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--queue-inslast-allhead,568000000,5.029274,8.854356 311 2023-04-06 23:04:58,2,5 10000 809 -1 2 ,./perfexp--upp-upp--stack-insfirst-remelem,590570000,5.018292,8.497370 312 2023-04-06 23:05:03,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-allhead,653200000,5.021467,7.687488 313 2023-04-06 23:05:08,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--queue-inslast-inselem,137599900,5.250703,38.159207 314 2023-04-06 23:05:14,4,5 100000 71 -1 4 ,./perfexp--upp-upp--queue-inslast-allhead,745500000,5.019787,6.733450 315 2023-04-06 23:05:19,1,5 10000 809 -1 1 ,./perfexp--upp-upp--queue-insfirst-inselem,412590000,5.039837,12.215122 316 2023-04-06 23:05:24,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--queue-inslast-inselem,724200000,5.013341,6.922592 317 2023-04-06 23:05:29,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--stack-inslast-allhead,603500000,5.026221,8.328452 318 2023-04-06 23:05:34,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-remelem,169890000,5.049109,29.719872 319 2023-04-06 23:05:39,4,5 10000 809 -1 4 ,./perfexp--upp-upp--stack-inslast-remelem,679560000,5.015714,7.380826 320 2023-04-06 23:05:44,2,5 100000 71 -1 2 ,./perfexp--upp-upp--stack-insfirst-remelem,731300000,5.037151,6.887941 321 2023-04-06 23:05:49,4,5 10000 809 -1 4 ,./perfexp--upp-upp--queue-inslast-remelem,614840000,5.059492,8.228957 322 2023-04-06 23:05:54,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-remelem,958500000,5.014201,5.231300 323 2023-04-06 23:05:59,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--stack-inslast-inselem,316785000,5.024996,15.862481 324 2023-04-06 23:06:04,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--queue-inslast-remelem,588315000,5.067089,8.612884 325 2023-04-06 23:06:09,2,5 100000 71 -1 2 ,./perfexp--upp-upp--stack-inslast-allhead,639000000,5.028277,7.868978 326 2023-04-06 23:06:14,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--queue-inslast-allhead,334887000,5.060557,15.111238 327 2023-04-06 23:06:19,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--queue-inslast-inselem,352989000,5.102670,14.455606 328 2023-04-06 23:06:25,4,5 100 72421 -1 4 ,./perfexp--upp-upp--queue-insfirst-allhead,130357800,5.098607,39.112404 329 2023-04-06 23:06:30,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--queue-inslast-inselem,144842000,5.151602,35.567045 330 2023-04-06 23:06:35,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--stack-insfirst-allhead,795200000,5.020810,6.313896 331 2023-04-06 23:06:40,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--stack-inslast-inselem,658000000,5.025127,7.636971 332 2023-04-06 23:06:45,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--stack-inslast-inselem,162918000,5.129739,31.486631 333 2023-04-06 23:06:50,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--stack-inslast-allhead,159326200,5.168959,32.442618 334 2023-04-06 23:06:55,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--queue-inslast-inselem,745500000,5.024930,6.740349 335 2023-04-06 23:07:00,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--stack-inslast-inselem,159326200,5.104196,32.036137 336 2023-04-06 23:07:06,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-allhead,575100000,5.018488,8.726288 337 2023-04-06 23:07:11,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-inselem,184600000,5.040923,27.307275 338 2023-04-06 23:07:16,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-allhead,162918000,5.129628,31.485950 339 2023-04-06 23:07:21,3,5 100000 71 -1 3 ,./perfexp--upp-upp--queue-insfirst-allhead,653200000,5.014120,7.676240 340 2023-04-06 23:07:26,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--stack-insfirst-allhead,903000000,5.007293,5.545175 341 2023-04-06 23:07:31,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-inselem,231000000,5.039397,21.815571 342 2023-04-06 23:07:36,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--stack-inslast-inselem,159326200,5.103728,32.033200 343 2023-04-06 23:07:41,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--queue-inslast-remelem,159326200,5.110623,32.076476 344 2023-04-06 23:07:46,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--queue-inslast-inselem,325836000,5.094063,15.633825 345 2023-04-06 23:07:51,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--queue-inslast-allhead,896000000,5.013412,5.595326 346 2023-04-06 23:07:56,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--queue-inslast-remelem,289684000,5.090448,17.572417 347 2023-04-06 23:08:01,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--queue-inslast-remelem,515907000,5.013509,9.717854 348 2023-04-06 23:08:06,1,5 10000 809 -1 1 ,./perfexp--upp-upp--stack-insfirst-remelem,582480000,5.028441,8.632813 349 2023-04-06 23:08:11,5,5 100 72421 -1 5 ,./perfexp--lq-list--stack-insfirst-allhead,166568300,5.049215,30.313181 350 2023-04-06 23:08:16,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-remelem,289684000,5.110068,17.640146 351 2023-04-06 23:08:22,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-inselem,343938000,5.103078,14.837203 352 2023-04-06 23:08:27,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-inselem,162918000,5.149009,31.604912 353 2023-04-06 23:08:32,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--stack-inslast-remelem,917000000,5.004999,5.458014 354 2023-04-06 23:08:37,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-remelem,695740000,5.052429,7.261950 355 2023-04-06 23:08:42,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-allhead,137599900,5.145265,37.392941 356 2023-04-06 23:08:47,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-inselem,159326200,5.189556,32.571893 357 2023-04-06 23:08:52,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--stack-inslast-remelem,177500000,5.052410,28.464282 358 2023-04-06 23:08:57,3,5 10000 809 -1 3 ,./perfexp--upp-upp--stack-insfirst-allhead,533940000,5.071980,9.499157 359 2023-04-06 23:09:03,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-allhead,665000000,5.021102,7.550529 360 2023-04-06 23:09:08,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--queue-insfirst-inselem,298683000,5.125385,17.159949 361 2023-04-06 23:09:13,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-remelem,579264000,5.001932,8.634978 362 2023-04-06 23:09:18,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-remelem,184600000,5.103404,27.645742 363 2023-04-06 23:09:23,3,5 100 72421 -1 3 ,./perfexp--upp-upp--stack-inslast-remelem,318652400,5.032572,15.793297 364 2023-04-06 23:09:28,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--queue-inslast-remelem,171969000,5.132165,29.843547 365 2023-04-06 23:09:33,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--stack-inslast-allhead,169890000,5.106152,30.055636 366 2023-04-06 23:09:38,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-remelem,720010000,5.056537,7.022871 367 2023-04-06 23:09:43,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--queue-inslast-remelem,169890000,5.068533,29.834204 368 2023-04-06 23:09:48,2,5 10000 809 -1 2 ,./perfexp--upp-upp--queue-inslast-allhead,493490000,5.018832,10.170078 369 2023-04-06 23:09:53,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--queue-inslast-inselem,833000000,5.016267,6.021929 370 2023-04-06 23:09:58,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--queue-inslast-allhead,461130000,5.084745,11.026706 371 2023-04-06 23:10:03,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--stack-inslast-inselem,908800000,5.035999,5.541372 372 2023-04-06 23:10:09,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--queue-inslast-allhead,889000000,5.028819,5.656714 373 2023-04-06 23:10:14,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--queue-inslast-allhead,166568300,5.191809,31.169250 374 2023-04-06 23:10:19,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--stack-inslast-inselem,159326200,5.152530,32.339502 375 2023-04-06 23:10:24,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--queue-inslast-remelem,289684000,5.093276,17.582179 376 2023-04-06 23:10:29,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-inselem,231000000,5.100410,22.079697 377 2023-04-06 23:10:34,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--queue-inslast-allhead,485400000,5.011748,10.324986 378 2023-04-06 23:10:39,5,5 100000 71 -1 5 ,./perfexp--upp-upp--queue-inslast-remelem,688700000,5.032312,7.306973 379 2023-04-06 23:10:44,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--queue-insfirst-inselem,973000000,5.027293,5.166797 380 2023-04-06 23:10:49,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-inselem,177980000,5.048409,28.365035 381 2023-04-06 23:10:54,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-allhead,159326200,5.095523,31.981702 382 2023-04-06 23:11:00,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-inselem,444950000,5.015660,11.272413 383 2023-04-06 23:11:05,3,5 1000000 7 -1 3 ,./perfexp--lq-list--stack-insfirst-allhead,924000000,5.029412,5.443087 384 2023-04-06 23:11:10,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--stack-inslast-allhead,343938000,5.134039,14.927222 385 2023-04-06 23:11:15,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--stack-insfirst-remelem,333136600,5.076445,15.238329 386 2023-04-06 23:11:20,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-inselem,169890000,5.039287,29.662058 387 2023-04-06 23:11:25,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--stack-insfirst-allhead,166568300,5.122763,30.754729 388 2023-04-06 23:11:30,4,5 100 72421 -1 4 ,./perfexp--upp-upp--stack-inslast-remelem,318652400,5.029359,15.783214 389 2023-04-06 23:11:35,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--queue-insfirst-allhead,1022000000,5.025006,4.916836 390 2023-04-06 23:11:40,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--queue-inslast-inselem,461130000,5.059408,10.971761 391 2023-04-06 23:11:45,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-allhead,159326200,5.102132,32.023183 392 2023-04-06 23:11:50,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-remelem,728100000,5.037604,6.918835 393 2023-04-06 23:11:56,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--queue-inslast-allhead,334887000,5.067591,15.132242 394 2023-04-06 23:12:01,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-inselem,159326200,5.104270,32.036602 395 2023-04-06 23:12:06,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--stack-inslast-inselem,184600000,5.124046,27.757562 396 2023-04-06 23:12:11,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--stack-inslast-allhead,1078000000,5.014921,4.652060 397 2023-04-06 23:12:16,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--stack-inslast-inselem,624800000,5.051553,8.085072 398 2023-04-06 23:12:21,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--queue-inslast-inselem,833000000,5.018805,6.024976 399 2023-04-06 23:12:26,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--queue-inslast-allhead,343938000,5.055123,14.697774 400 2023-04-06 23:12:31,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--queue-insfirst-allhead,316785000,5.093298,16.078091 401 2023-04-06 23:12:36,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--queue-inslast-allhead,144842000,5.158022,35.611370 402 2023-04-06 23:12:41,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--stack-inslast-allhead,159326200,5.152787,32.341115 403 2023-04-06 23:12:47,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-allhead,181020000,5.246972,28.985593 404 2023-04-06 23:12:52,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-remelem,171969000,5.244708,30.497985 405 2023-04-06 23:12:57,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--queue-inslast-remelem,289684000,5.088471,17.565592 406 2023-04-06 23:13:02,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-remelem,720010000,5.055206,7.021022 407 2023-04-06 23:13:07,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--queue-inslast-allhead,560900000,5.032860,8.972829 408 2023-04-06 23:13:12,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--queue-inslast-allhead,959000000,5.008545,5.222675 409 2023-04-06 23:13:17,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--stack-insfirst-remelem,784000000,5.022341,6.406047 410 2023-04-06 23:13:22,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--queue-inslast-inselem,352989000,5.117729,14.498268 411 2023-04-06 23:13:27,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--queue-inslast-inselem,224000000,5.066051,22.616299 412 2023-04-06 23:13:33,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-remelem,159326200,5.077187,31.866617 413 2023-04-06 23:13:38,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--stack-inslast-inselem,166568300,5.220717,31.342801 414 2023-04-06 23:13:43,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--queue-inslast-inselem,477310000,5.070365,10.622792 415 2023-04-06 23:13:48,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--queue-insfirst-remelem,1309000000,5.007603,3.825518 416 2023-04-06 23:13:53,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-allhead,184600000,5.111904,27.691788 417 2023-04-06 23:13:58,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-remelem,972700000,5.036058,5.177401 418 2023-04-06 23:14:03,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--stack-inslast-remelem,938000000,5.030859,5.363389 419 2023-04-06 23:14:08,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-inselem,231000000,5.144215,22.269329 420 2023-04-06 23:14:13,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-allhead,159326200,5.195831,32.611278 421 2023-04-06 23:14:19,5,5 100000 71 -1 5 ,./perfexp--upp-upp--queue-insfirst-remelem,710000000,5.050419,7.113266 422 2023-04-06 23:14:24,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--stack-inslast-inselem,477310000,5.056472,10.593685 423 2023-04-06 23:14:29,1,5 100000 71 -1 1 ,./perfexp--upp-upp--stack-inslast-allhead,646100000,5.033754,7.790983 424 2023-04-06 23:14:34,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--queue-inslast-inselem,169890000,5.007809,29.476773 425 2023-04-06 23:14:39,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-remelem,184600000,5.140697,27.847763 426 2023-04-06 23:14:44,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-remelem,917000000,5.012871,5.466599 427 2023-04-06 23:14:49,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--stack-inslast-remelem,792820000,5.025219,6.338411 428 2023-04-06 23:14:54,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-allhead,184600000,5.077734,27.506685 429 2023-04-06 23:14:59,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--stack-inslast-allhead,231000000,5.142791,22.263165 430 2023-04-06 23:15:04,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--queue-inslast-inselem,334887000,5.004776,14.944671 431 2023-04-06 23:15:09,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--queue-inslast-allhead,144842000,5.161848,35.637785 432 2023-04-06 23:15:15,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--stack-insfirst-inselem,325836000,5.085281,15.606873 433 2023-04-06 23:15:20,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--stack-insfirst-inselem,581000000,5.020173,8.640573 434 2023-04-06 23:15:25,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--queue-inslast-inselem,710000000,5.014337,7.062446 435 2023-04-06 23:15:30,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-allhead,177980000,5.062496,28.444185 436 2023-04-06 23:15:35,1,5 1000000 7 -1 1 ,./perfexp--lq-list--stack-insfirst-allhead,917000000,5.004475,5.457443 437 2023-04-06 23:15:40,4,5 100 72421 -1 4 ,./perfexp--upp-upp--queue-inslast-remelem,267957700,5.136059,19.167425 438 2023-04-06 23:15:45,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--stack-inslast-remelem,687876000,5.053524,7.346562 439 2023-04-06 23:15:50,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-allhead,444950000,5.008229,11.255712 440 2023-04-06 23:15:55,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--queue-inslast-remelem,159326200,5.159661,32.384259 441 2023-04-06 23:16:00,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--queue-insfirst-allhead,453040000,5.007535,11.053185 442 2023-04-06 23:16:05,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-inselem,224000000,5.009136,22.362214 443 2023-04-06 23:16:10,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--queue-inslast-allhead,453040000,5.019570,11.079750 444 2023-04-06 23:16:15,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--stack-inslast-allhead,159326200,5.106386,32.049883 445 2023-04-06 23:16:20,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--stack-inslast-allhead,162918000,5.082855,31.198855 446 2023-04-06 23:16:26,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--queue-insfirst-remelem,944300000,5.025435,5.321863 447 2023-04-06 23:16:31,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--queue-insfirst-allhead,130357800,5.062806,38.837768 448 2023-04-06 23:16:36,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-remelem,171969000,5.121176,29.779646 449 2023-04-06 23:16:41,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--queue-insfirst-remelem,861000000,5.036872,5.850026 450 2023-04-06 23:16:46,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--stack-inslast-remelem,720010000,5.033713,6.991171 451 2023-04-06 23:16:51,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--queue-insfirst-inselem,766800000,5.001069,6.521999 452 2023-04-06 23:16:56,5,5 100 72421 -1 5 ,./perfexp--upp-upp--stack-insfirst-allhead,159326200,5.154320,32.350737 453 2023-04-06 23:17:01,1,5 100000 71 -1 1 ,./perfexp--upp-upp--queue-inslast-inselem,610600000,5.008342,8.202329 454 2023-04-06 23:17:06,3,5 100000 71 -1 3 ,./perfexp--lq-list--stack-insfirst-allhead,802300000,5.014286,6.249889 455 2023-04-06 23:17:11,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--stack-inslast-allhead,231000000,5.088531,22.028273 456 2023-04-06 23:17:16,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--stack-inslast-inselem,343938000,5.070875,14.743573 457 2023-04-06 23:17:21,4,5 10000 809 -1 4 ,./perfexp--upp-upp--queue-insfirst-allhead,444950000,5.042555,11.332858 458 2023-04-06 23:17:26,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--stack-inslast-remelem,658000000,5.001245,7.600676 459 2023-04-06 23:17:31,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--queue-inslast-remelem,515907000,5.021599,9.733535 460 2023-04-06 23:17:36,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-inselem,159326200,5.186501,32.552719 461 2023-04-06 23:17:42,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-inselem,177980000,5.026446,28.241634 462 2023-04-06 23:17:47,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--stack-inslast-inselem,658000000,5.016281,7.623527 463 2023-04-06 23:17:52,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--queue-inslast-remelem,784000000,5.003437,6.381935 464 2023-04-06 23:17:57,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--stack-inslast-remelem,347620800,5.029484,14.468306 465 2023-04-06 23:18:02,1,5 100000 71 -1 1 ,./perfexp--upp-upp--queue-inslast-remelem,710000000,5.007576,7.052924 466 2023-04-06 23:18:07,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--queue-inslast-remelem,809400000,5.015371,6.196406 467 2023-04-06 23:18:12,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--queue-insfirst-allhead,788100000,5.040980,6.396371 468 2023-04-06 23:18:17,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--queue-inslast-inselem,461130000,5.057431,10.967473 469 2023-04-06 23:18:22,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-remelem,159326200,5.044365,31.660612 470 2023-04-06 23:18:27,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-allhead,485400000,5.070348,10.445711 471 2023-04-06 23:18:32,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--stack-inslast-inselem,316785000,5.018884,15.843187 472 2023-04-06 23:18:37,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-inselem,560900000,5.062667,9.025971 473 2023-04-06 23:18:42,5,5 10000 809 -1 5 ,./perfexp--upp-upp--queue-insfirst-inselem,412590000,5.015951,12.157229 474 2023-04-06 23:18:47,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--queue-insfirst-inselem,816500000,5.000448,6.124247 475 2023-04-06 23:18:52,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--stack-inslast-inselem,162918000,5.018924,30.806443 476 2023-04-06 23:18:57,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--queue-inslast-remelem,695740000,5.044067,7.249931 477 2023-04-06 23:19:03,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--queue-inslast-remelem,169890000,5.075488,29.875143 478 2023-04-06 23:19:08,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--queue-inslast-inselem,224000000,5.038191,22.491924 479 2023-04-06 23:19:13,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--stack-insfirst-inselem,325836000,5.103653,15.663257 480 2023-04-06 23:19:18,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-allhead,444950000,5.010533,11.260890 481 2023-04-06 23:19:23,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--queue-inslast-allhead,224000000,5.004062,22.339563 482 2023-04-06 23:19:28,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--queue-inslast-remelem,784000000,5.030273,6.416165 483 2023-04-06 23:19:33,1,5 10000 809 -1 1 ,./perfexp--upp-upp--stack-insfirst-inselem,485400000,5.050046,10.403885 484 2023-04-06 23:19:38,1,5 100000 71 -1 1 ,./perfexp--upp-upp--stack-insfirst-inselem,617700000,5.005519,8.103479 485 2023-04-06 23:19:43,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--stack-insfirst-allhead,325836000,5.106682,15.672553 486 2023-04-06 23:19:48,3,5 100000 71 -1 3 ,./perfexp--upp-upp--queue-insfirst-remelem,681600000,5.046878,7.404457 487 2023-04-06 23:19:53,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-inselem,137599900,5.148273,37.414802 488 2023-04-06 23:19:58,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--stack-inslast-inselem,603500000,5.030745,8.335949 489 2023-04-06 23:20:03,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--stack-inslast-inselem,987000000,5.001494,5.067370 490 2023-04-06 23:20:08,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--queue-inslast-allhead,144842000,5.159197,35.619482 491 2023-04-06 23:20:14,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-inselem,453040000,5.069119,11.189120 492 2023-04-06 23:20:19,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--stack-inslast-inselem,880400000,5.006800,5.686960 493 2023-04-06 23:20:24,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-allhead,224000000,5.105644,22.793054 494 2023-04-06 23:20:29,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-remelem,224000000,5.045045,22.522522 495 2023-04-06 23:20:34,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--queue-inslast-allhead,959000000,5.008714,5.222851 496 2023-04-06 23:20:39,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--queue-inslast-inselem,184600000,5.185437,28.090125 497 2023-04-06 23:20:44,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--stack-insfirst-inselem,420680000,5.058743,12.025157 498 2023-04-06 23:20:49,3,5 100 72421 -1 3 ,./perfexp--upp-upp--queue-insfirst-remelem,260715600,5.111093,19.604094 499 2023-04-06 23:20:54,2,5 100000 71 -1 2 ,./perfexp--upp-upp--stack-insfirst-allhead,773900000,5.004333,6.466382 500 2023-04-06 23:20:59,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--queue-insfirst-remelem,812000000,5.021316,6.183887 501 2023-04-06 23:21:04,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-allhead,184600000,5.041771,27.311869 502 2023-04-06 23:21:09,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--stack-inslast-remelem,1414000000,5.000733,3.536586 503 2023-04-06 23:21:14,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-remelem,289684000,5.112781,17.649511 504 2023-04-06 23:21:20,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--stack-insfirst-inselem,539600000,5.009402,9.283547 505 2023-04-06 23:21:25,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--stack-inslast-inselem,325836000,5.128478,15.739446 506 2023-04-06 23:21:30,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--stack-insfirst-allhead,509670000,5.040138,9.889022 507 2023-04-06 23:21:35,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--queue-insfirst-inselem,307734000,5.031918,16.351518 508 2023-04-06 23:21:40,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-remelem,588315000,5.069535,8.617042 509 2023-04-06 23:21:45,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-allhead,181020000,5.196558,28.707093 510 2023-04-06 23:21:50,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--queue-insfirst-remelem,720010000,5.049517,7.013121 511 2023-04-06 23:21:55,2,5 100000 71 -1 2 ,./perfexp--upp-upp--stack-insfirst-inselem,631900000,5.011261,7.930465 512 2023-04-06 23:22:00,4,5 100 72421 -1 4 ,./perfexp--upp-upp--queue-inslast-inselem,137599900,5.090919,36.997985 513 2023-04-06 23:22:05,3,5 100000 71 -1 3 ,./perfexp--lq-list--stack-insfirst-remelem,688700000,5.028916,7.302042 514 2023-04-06 23:22:10,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--queue-inslast-inselem,159326200,5.021214,31.515306 515 2023-04-06 23:22:15,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--stack-inslast-allhead,343938000,5.134953,14.929880 516 2023-04-06 23:22:21,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--stack-insfirst-allhead,766800000,5.010735,6.534605 517 2023-04-06 23:22:26,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-remelem,588315000,5.005341,8.507927 518 2023-04-06 23:22:31,5,5 100000 71 -1 5 ,./perfexp--upp-upp--stack-inslast-inselem,553800000,5.022399,9.068976 519 2023-04-06 23:22:36,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-inselem,217000000,5.090764,23.459742 520 2023-04-06 23:22:41,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--queue-insfirst-allhead,316785000,5.107048,16.121496 521 2023-04-06 23:22:46,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-inselem,603500000,5.007173,8.296890 522 2023-04-06 23:22:51,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--stack-insfirst-remelem,534009000,5.013222,9.387898 523 2023-04-06 23:22:56,4,5 100000 71 -1 4 ,./perfexp--upp-upp--queue-inslast-inselem,617700000,5.049209,8.174209 524 2023-04-06 23:23:01,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--stack-inslast-inselem,159326200,5.098883,32.002791 525 2023-04-06 23:23:06,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--queue-inslast-allhead,224000000,5.012905,22.379040 526 2023-04-06 23:23:11,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--queue-inslast-inselem,693000000,5.010052,7.229512 527 2023-04-06 23:23:16,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--stack-inslast-inselem,343938000,5.081110,14.773331 528 2023-04-06 23:23:21,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--stack-insfirst-allhead,805000000,5.000210,6.211441 529 2023-04-06 23:23:26,2,5 10000 809 -1 2 ,./perfexp--lq-list--stack-insfirst-inselem,420680000,5.069851,12.051562 530 2023-04-06 23:23:31,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-inselem,177980000,5.051407,28.381880 531 2023-04-06 23:23:36,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--stack-inslast-inselem,987000000,5.007191,5.073142 532 2023-04-06 23:23:41,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-remelem,231000000,5.081453,21.997632 533 2023-04-06 23:23:46,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-remelem,177500000,5.017600,28.268169 534 2023-04-06 23:23:52,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-inselem,343938000,5.100129,14.828629 535 2023-04-06 23:23:57,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-inselem,184600000,5.151028,27.903727 536 2023-04-06 23:24:02,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-remelem,184600000,5.128629,27.782389 537 2023-04-06 23:24:07,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-remelem,910000000,5.002322,5.497057 538 2023-04-06 23:24:12,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-allhead,177980000,5.196302,29.195988 539 2023-04-06 23:24:17,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--stack-insfirst-allhead,509670000,5.014897,9.839498 540 2023-04-06 23:24:22,2,5 100 72421 -1 2 ,./perfexp--upp-upp--queue-insfirst-remelem,260715600,5.109786,19.599080 541 2023-04-06 23:24:27,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--stack-inslast-inselem,159326200,5.008081,31.432878 542 2023-04-06 23:24:32,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--queue-inslast-inselem,325836000,5.116265,15.701964 543 2023-04-06 23:24:37,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--stack-inslast-remelem,570213000,5.046808,8.850742 544 2023-04-06 23:24:43,2,5 100 72421 -1 2 ,./perfexp--upp-upp--queue-inslast-allhead,137599900,5.042300,36.644649 545 2023-04-06 23:24:48,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-allhead,665000000,5.022941,7.553295 546 2023-04-06 23:24:53,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-remelem,153867000,5.092858,33.099092 547 2023-04-06 23:24:58,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--queue-insfirst-inselem,966000000,5.015365,5.191889 548 2023-04-06 23:25:03,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--stack-inslast-inselem,177980000,5.188118,29.150006 549 2023-04-06 23:25:08,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--queue-insfirst-remelem,296926100,5.109709,17.208689 550 2023-04-06 23:25:13,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-remelem,184600000,5.118232,27.726067 551 2023-04-06 23:25:18,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--queue-inslast-allhead,177980000,5.168805,29.041493 552 2023-04-06 23:25:23,2,5 100 72421 -1 2 ,./perfexp--upp-upp--stack-inslast-allhead,159326200,5.074931,31.852457 553 2023-04-06 23:25:28,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--queue-insfirst-remelem,534009000,5.064100,9.483174 554 2023-04-06 23:25:34,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--queue-insfirst-allhead,130357800,5.062901,38.838497 555 2023-04-06 23:25:39,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--queue-inslast-inselem,184600000,5.176605,28.042281 556 2023-04-06 23:25:44,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--queue-inslast-inselem,137599900,5.248929,38.146314 557 2023-04-06 23:25:49,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-inselem,184600000,5.090988,27.578483 558 2023-04-06 23:25:54,2,5 10000 809 -1 2 ,./perfexp--lq-list--stack-insfirst-remelem,590570000,5.053093,8.556298 559 2023-04-06 23:25:59,1,5 10000 809 -1 1 ,./perfexp--upp-upp--queue-inslast-remelem,614840000,5.005980,8.141923 560 2023-04-06 23:26:04,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--queue-inslast-allhead,171969000,5.032441,29.263652 561 2023-04-06 23:26:09,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--queue-inslast-allhead,485400000,5.027026,10.356461 562 2023-04-06 23:26:14,5,5 100000 71 -1 5 ,./perfexp--upp-upp--queue-inslast-allhead,695800000,5.023256,7.219396 563 2023-04-06 23:26:19,2,5 100000 71 -1 2 ,./perfexp--lq-list--stack-insfirst-inselem,738400000,5.023025,6.802580 564 2023-04-06 23:26:24,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-allhead,546700000,5.016473,9.175915 565 2023-04-06 23:26:29,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-inselem,181020000,5.192822,28.686455 566 2023-04-06 23:26:35,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-inselem,343938000,5.093426,14.809140 567 2023-04-06 23:26:40,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-remelem,153867000,5.079586,33.012836 568 2023-04-06 23:26:45,5,5 10000 809 -1 5 ,./perfexp--lq-list--stack-insfirst-inselem,509670000,5.077423,9.962177 569 2023-04-06 23:26:50,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-remelem,169890000,5.078467,29.892678 570 2023-04-06 23:26:55,3,5 100 72421 -1 3 ,./perfexp--upp-upp--stack-inslast-inselem,159326200,5.146163,32.299540 571 2023-04-06 23:27:00,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--stack-inslast-allhead,159326200,5.163047,32.405511 572 2023-04-06 23:27:05,4,5 100000 71 -1 4 ,./perfexp--upp-upp--queue-insfirst-inselem,568000000,5.058001,8.904931 573 2023-04-06 23:27:11,3,5 10000 809 -1 3 ,./perfexp--lq-list--stack-insfirst-inselem,485400000,5.006967,10.315136 574 2023-04-06 23:27:16,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--stack-inslast-inselem,617700000,5.005977,8.104220 575 2023-04-06 23:27:21,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--queue-insfirst-inselem,588000000,5.020572,8.538388 576 2023-04-06 23:27:26,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--queue-inslast-remelem,777000000,5.025727,6.468117 577 2023-04-06 23:27:31,4,5 100000 71 -1 4 ,./perfexp--upp-upp--stack-inslast-inselem,553800000,5.014991,9.055599 578 2023-04-06 23:27:36,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--stack-insfirst-remelem,461601000,5.001793,10.835750 579 2023-04-06 23:27:41,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--queue-inslast-remelem,224000000,5.052311,22.554960 580 2023-04-06 23:27:46,2,5 10000 809 -1 2 ,./perfexp--upp-upp--queue-insfirst-inselem,412590000,5.009318,12.141152 581 2023-04-06 23:27:51,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--queue-inslast-allhead,781000000,5.043798,6.458128 582 2023-04-06 23:27:56,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-remelem,703830000,5.055801,7.183270 583 2023-04-06 23:28:01,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-remelem,184600000,5.103939,27.648640 584 2023-04-06 23:28:06,2,5 100 72421 -1 2 ,./perfexp--upp-upp--stack-insfirst-allhead,159326200,5.157636,32.371550 585 2023-04-06 23:28:11,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-remelem,318652400,5.003554,15.702232 586 2023-04-06 23:28:16,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-allhead,617700000,5.007486,8.106663 587 2023-04-06 23:28:21,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-remelem,231000000,5.082904,22.003913 588 2023-04-06 23:28:26,5,5 100000 71 -1 5 ,./perfexp--upp-upp--stack-inslast-remelem,823600000,5.035229,6.113683 589 2023-04-06 23:28:31,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--queue-inslast-allhead,539600000,5.014691,9.293349 590 2023-04-06 23:28:36,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--queue-inslast-allhead,137599900,5.146557,37.402331 591 2023-04-06 23:28:42,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--queue-inslast-allhead,166568300,5.151938,30.929883 592 2023-04-06 23:28:47,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--queue-insfirst-inselem,595000000,5.045803,8.480341 593 2023-04-06 23:28:52,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--queue-inslast-inselem,453040000,5.084859,11.223863 594 2023-04-06 23:28:57,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-inselem,159326200,5.191003,32.580975 595 2023-04-06 23:29:02,5,5 10000 809 -1 5 ,./perfexp--upp-upp--stack-inslast-remelem,687650000,5.026542,7.309739 596 2023-04-06 23:29:07,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-remelem,159326200,5.092534,31.962941 597 2023-04-06 23:29:12,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--queue-insfirst-remelem,720010000,5.046402,7.008794 598 2023-04-06 23:29:17,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-allhead,184600000,5.093610,27.592687 599 2023-04-06 23:29:22,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--stack-inslast-allhead,343938000,5.130926,14.918171 600 2023-04-06 23:29:28,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--queue-inslast-inselem,144842000,5.154669,35.588220 601 2023-04-06 23:29:33,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--stack-insfirst-allhead,781000000,5.027590,6.437375 602 2023-04-06 23:29:38,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--stack-inslast-allhead,469220000,5.020177,10.698983 603 2023-04-06 23:29:43,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--stack-inslast-allhead,672000000,5.049259,7.513778 604 2023-04-06 23:29:48,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--queue-inslast-remelem,590570000,5.015500,8.492643 605 2023-04-06 23:29:53,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--queue-inslast-remelem,515907000,5.032712,9.755076 606 2023-04-06 23:29:58,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--queue-inslast-inselem,325836000,5.107450,15.674910 607 2023-04-06 23:30:03,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--stack-inslast-remelem,800910000,5.026620,6.276136 608 2023-04-06 23:30:08,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--stack-inslast-remelem,347620800,5.041880,14.503965 609 2023-04-06 23:30:13,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-allhead,231000000,5.013901,21.705199 610 2023-04-06 23:30:18,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--queue-inslast-remelem,171969000,5.137606,29.875187 611 2023-04-06 23:30:23,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--stack-inslast-allhead,770000000,5.003343,6.497848 612 2023-04-06 23:30:28,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-allhead,166568300,5.108504,30.669125 613 2023-04-06 23:30:34,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--queue-inslast-allhead,184600000,5.156994,27.936046 614 2023-04-06 23:30:39,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--stack-insfirst-allhead,819000000,5.014858,6.123148 615 2023-04-06 23:30:44,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--stack-inslast-remelem,1414000000,5.003794,3.538751 616 2023-04-06 23:30:49,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-inselem,231000000,5.035501,21.798706 617 2023-04-06 23:30:54,1,5 100 72421 -1 1 ,./perfexp--upp-upp--stack-insfirst-inselem,159326200,5.209153,32.694893 618 2023-04-06 23:30:59,4,5 10000 809 -1 4 ,./perfexp--upp-upp--stack-insfirst-inselem,477310000,5.023267,10.524118 619 2023-04-06 23:31:04,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--stack-insfirst-inselem,325836000,5.101399,15.656339 620 2023-04-06 23:31:09,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--queue-inslast-remelem,667400000,5.022926,7.526110 621 2023-04-06 23:31:14,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--stack-inslast-remelem,325894500,5.091748,15.623915 622 2023-04-06 23:31:19,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-allhead,334887000,5.054765,15.093942 623 2023-04-06 23:31:24,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-remelem,1008000000,5.001067,4.961376 624 2023-04-06 23:31:29,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--stack-insfirst-inselem,679000000,5.016446,7.387991 625 2023-04-06 23:31:35,5,5 1000000 7 -1 5 ,./perfexp--lq-list--stack-insfirst-remelem,798000000,5.020158,6.290925 626 2023-04-06 23:31:40,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-inselem,658000000,5.046821,7.669941 627 2023-04-06 23:31:45,2,5 10000 809 -1 2 ,./perfexp--upp-upp--stack-insfirst-inselem,469220000,5.064185,10.792773 628 2023-04-06 23:31:50,4,5 100000 71 -1 4 ,./perfexp--upp-upp--stack-insfirst-inselem,674500000,5.015829,7.436366 629 2023-04-06 23:31:55,2,5 10000 809 -1 2 ,./perfexp--upp-upp--queue-insfirst-remelem,639110000,5.034318,7.877076 630 2023-04-06 23:32:00,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--stack-inslast-remelem,570213000,5.053420,8.862337 631 2023-04-06 23:32:05,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--queue-inslast-allhead,171969000,5.028685,29.241811 632 2023-04-06 23:32:10,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--queue-inslast-remelem,224000000,5.019890,22.410223 633 2023-04-06 23:32:15,4,5 10000 809 -1 4 ,./perfexp--upp-upp--queue-insfirst-remelem,582480000,5.025035,8.626966 634 2023-04-06 23:32:20,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-remelem,161800000,5.127857,31.692565 635 2023-04-06 23:32:25,1,5 100 72421 -1 1 ,./perfexp--upp-upp--queue-inslast-remelem,260715600,5.019198,19.251621 636 2023-04-06 23:32:30,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-allhead,162918000,5.129510,31.485226 637 2023-04-06 23:32:35,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--queue-insfirst-inselem,130357800,5.149737,39.504633 638 2023-04-06 23:32:40,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-remelem,162918000,5.005389,30.723364 639 2023-04-06 23:32:45,3,5 100000 71 -1 3 ,./perfexp--upp-upp--queue-inslast-allhead,695800000,5.049924,7.257723 640 2023-04-06 23:32:50,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--queue-insfirst-inselem,973000000,5.026228,5.165702 641 2023-04-06 23:32:56,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--stack-inslast-inselem,184600000,5.070150,27.465601 642 2023-04-06 23:33:01,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--queue-inslast-allhead,171969000,5.038940,29.301444 643 2023-04-06 23:33:06,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--stack-insfirst-allhead,352989000,5.128804,14.529643 644 2023-04-06 23:33:11,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--stack-inslast-remelem,1313500000,5.022908,3.824064 645 2023-04-06 23:33:16,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--stack-inslast-inselem,224000000,5.068988,22.629411 646 2023-04-06 23:33:21,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--stack-insfirst-inselem,420680000,5.058039,12.023483 647 2023-04-06 23:33:26,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--stack-inslast-remelem,597366000,5.067353,8.482828 648 2023-04-06 23:33:31,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-inselem,171969000,5.047845,29.353226 649 2023-04-06 23:33:36,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--stack-inslast-remelem,809000000,5.044723,6.235752 650 2023-04-06 23:33:41,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--queue-inslast-remelem,589300000,5.035557,8.544980 651 2023-04-06 23:33:46,4,5 100000 71 -1 4 ,./perfexp--upp-upp--queue-inslast-remelem,717100000,5.046045,7.036738 652 2023-04-06 23:33:51,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-remelem,597366000,5.069419,8.486286 653 2023-04-06 23:33:56,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--queue-insfirst-remelem,868000000,5.025089,5.789273 654 2023-04-06 23:34:01,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--stack-inslast-inselem,658000000,5.025487,7.637518 655 2023-04-06 23:34:06,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--queue-inslast-remelem,980000000,5.009915,5.112158 656 2023-04-06 23:34:11,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--queue-inslast-remelem,823600000,5.002809,6.074319 657 2023-04-06 23:34:16,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-remelem,231000000,5.141988,22.259688 658 2023-04-06 23:34:22,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--queue-insfirst-remelem,642621000,5.057599,7.870267 659 2023-04-06 23:34:27,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--stack-inslast-inselem,184600000,5.153607,27.917698 660 2023-04-06 23:34:32,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--stack-inslast-inselem,658000000,5.017245,7.624992 661 2023-04-06 23:34:37,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-allhead,485400000,5.077844,10.461154 662 2023-04-06 23:34:42,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--queue-inslast-remelem,217000000,5.099401,23.499544 663 2023-04-06 23:34:47,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--queue-inslast-inselem,658000000,5.013213,7.618865 664 2023-04-06 23:34:52,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--stack-insfirst-remelem,590570000,5.033234,8.522671 665 2023-04-06 23:34:57,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--stack-inslast-inselem,316785000,5.046378,15.929978 666 2023-04-06 23:35:02,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--queue-inslast-remelem,159326200,5.120925,32.141136 667 2023-04-06 23:35:07,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--stack-inslast-allhead,334887000,5.038462,15.045260 668 2023-04-06 23:35:12,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--stack-inslast-inselem,231000000,5.148560,22.288139 669 2023-04-06 23:35:18,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-inselem,169890000,5.124945,30.166255 670 2023-04-06 23:35:23,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--queue-inslast-inselem,553800000,5.003500,9.034850 671 2023-04-06 23:35:28,3,5 1000 9051 -1 3 ,./perfexp--lq-list--stack-insfirst-remelem,534009000,5.006456,9.375228 672 2023-04-06 23:35:33,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-allhead,624800000,5.050627,8.083590 673 2023-04-06 23:35:38,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--queue-insfirst-remelem,642621000,5.039619,7.842288 674 2023-04-06 23:35:43,3,5 1000000 7 -1 3 ,./perfexp--lq-list--stack-insfirst-inselem,574000000,5.031817,8.766232 675 2023-04-06 23:35:48,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--queue-inslast-inselem,137599900,5.246307,38.127259 676 2023-04-06 23:35:53,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--stack-inslast-allhead,501580000,5.012750,9.993919 677 2023-04-06 23:35:58,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--stack-inslast-inselem,325836000,5.131221,15.747864 678 2023-04-06 23:36:03,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--stack-inslast-allhead,159326200,5.111924,32.084641 679 2023-04-06 23:36:09,2,5 10000 809 -1 2 ,./perfexp--upp-upp--queue-inslast-remelem,606750000,5.003928,8.247100 680 2023-04-06 23:36:14,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--queue-inslast-allhead,582200000,5.022484,8.626733 681 2023-04-06 23:36:19,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--stack-inslast-inselem,166568300,5.222978,31.356375 682 2023-04-06 23:36:24,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--stack-inslast-allhead,162918000,5.101216,31.311556 683 2023-04-06 23:36:29,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--queue-inslast-allhead,959000000,5.005860,5.219875 684 2023-04-06 23:36:34,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--queue-insfirst-inselem,307734000,5.025667,16.331205 685 2023-04-06 23:36:39,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--stack-inslast-remelem,588315000,5.002182,8.502557 686 2023-04-06 23:36:44,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--stack-inslast-remelem,153867000,5.230752,33.995282 687 2023-04-06 23:36:49,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-remelem,152084100,5.127175,33.712762 688 2023-04-06 23:36:54,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--stack-inslast-remelem,784730000,5.021496,6.399011 689 2023-04-06 23:37:00,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--queue-insfirst-allhead,1022000000,5.025863,4.917674 690 2023-04-06 23:37:05,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-inselem,444950000,5.083193,11.424189 691 2023-04-06 23:37:10,4,5 1000 9051 -1 4 ,./perfexp--lq-list--stack-insfirst-inselem,325836000,5.104508,15.665881 692 2023-04-06 23:37:15,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-allhead,224000000,5.044330,22.519330 693 2023-04-06 23:37:20,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--stack-inslast-inselem,658000000,5.008834,7.612210 694 2023-04-06 23:37:25,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--queue-insfirst-allhead,461130000,5.088815,11.035532 695 2023-04-06 23:37:30,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--queue-insfirst-remelem,534009000,5.067296,9.489158 696 2023-04-06 23:37:35,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--stack-inslast-inselem,162918000,5.085345,31.214138 697 2023-04-06 23:37:40,3,5 1000 9051 -1 3 ,./perfexp--lq-list--stack-insfirst-allhead,343938000,5.058624,14.707953 698 2023-04-06 23:37:45,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-inselem,658000000,5.050619,7.675713 699 2023-04-06 23:37:50,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--queue-insfirst-inselem,130357800,5.147518,39.487610 700 2023-04-06 23:37:55,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--queue-inslast-remelem,606750000,5.060103,8.339684 701 2023-04-06 23:38:00,4,5 10000 809 -1 4 ,./perfexp--lq-list--stack-insfirst-allhead,509670000,5.013006,9.835788 702 2023-04-06 23:38:06,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-allhead,665000000,5.030220,7.564241 703 2023-04-06 23:38:11,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--stack-insfirst-allhead,509670000,5.045241,9.899035 704 2023-04-06 23:38:16,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--stack-inslast-remelem,707000000,5.030443,7.115195 705 2023-04-06 23:38:21,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--stack-inslast-allhead,1036600000,5.005349,4.828621 706 2023-04-06 23:38:26,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--stack-insfirst-allhead,166568300,5.122366,30.752346 707 2023-04-06 23:38:31,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--stack-inslast-remelem,720010000,5.032318,6.989233 708 2023-04-06 23:38:36,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--stack-inslast-allhead,1078000000,5.011085,4.648502 709 2023-04-06 23:38:41,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--stack-insfirst-remelem,693000000,5.044421,7.279107 710 2023-04-06 23:38:46,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-inselem,217000000,5.008831,23.082171 711 2023-04-06 23:38:51,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--stack-inslast-inselem,980000000,5.001764,5.103841 712 2023-04-06 23:38:56,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--stack-inslast-allhead,159326200,5.160432,32.389099 713 2023-04-06 23:39:01,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-remelem,994000000,5.009426,5.039664 714 2023-04-06 23:39:06,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--stack-inslast-allhead,1008200000,5.006411,4.965692 715 2023-04-06 23:39:11,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--queue-insfirst-allhead,679000000,5.010746,7.379596 716 2023-04-06 23:39:16,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-remelem,588315000,5.073975,8.624589 717 2023-04-06 23:39:21,1,5 100 72421 -1 1 ,./perfexp--upp-upp--stack-insfirst-remelem,267957700,5.034365,18.787909 718 2023-04-06 23:39:26,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--queue-insfirst-remelem,534009000,5.054075,9.464400 719 2023-04-06 23:39:31,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--queue-inslast-allhead,665000000,5.000117,7.518973 720 2023-04-06 23:39:36,5,5 100 72421 -1 5 ,./perfexp--upp-upp--queue-inslast-allhead,137599900,5.044078,36.657570 721 2023-04-06 23:39:42,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--stack-inslast-remelem,224000000,5.024699,22.431692 722 2023-04-06 23:39:47,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-allhead,665000000,5.038271,7.576347 723 2023-04-06 23:39:52,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-inselem,137599900,5.151879,37.441008 724 2023-04-06 23:39:57,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--queue-inslast-inselem,137599900,5.247585,38.136547 725 2023-04-06 23:40:02,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-allhead,159326200,5.203331,32.658351 726 2023-04-06 23:40:07,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--stack-inslast-remelem,347620800,5.038125,14.493163 727 2023-04-06 23:40:12,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-allhead,532500000,5.009917,9.408295 728 2023-04-06 23:40:17,2,5 100000 71 -1 2 ,./perfexp--lq-list--stack-insfirst-remelem,681600000,5.024278,7.371300 729 2023-04-06 23:40:22,5,5 1000 9051 -1 5 ,./perfexp--lq-list--stack-insfirst-remelem,534009000,5.005566,9.373561 730 2023-04-06 23:40:27,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-remelem,588315000,5.056992,8.595722 731 2023-04-06 23:40:32,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--queue-inslast-inselem,144842000,5.153273,35.578582 732 2023-04-06 23:40:38,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--stack-insfirst-allhead,945000000,5.002845,5.294016 733 2023-04-06 23:40:43,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--queue-inslast-allhead,343938000,5.058633,14.707979 734 2023-04-06 23:40:48,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--stack-insfirst-inselem,420680000,5.068194,12.047623 735 2023-04-06 23:40:53,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--stack-inslast-allhead,1078000000,5.010055,4.647546 736 2023-04-06 23:40:58,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-remelem,184600000,5.101831,27.637221 737 2023-04-06 23:41:03,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--queue-insfirst-remelem,854000000,5.009771,5.866242 738 2023-04-06 23:41:08,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--stack-inslast-inselem,316785000,5.026464,15.867115 739 2023-04-06 23:41:13,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-inselem,444950000,5.000762,11.238930 740 2023-04-06 23:41:18,2,5 100000 71 -1 2 ,./perfexp--upp-upp--queue-inslast-remelem,702900000,5.023292,7.146524 741 2023-04-06 23:41:23,4,5 10000 809 -1 4 ,./perfexp--upp-upp--stack-insfirst-remelem,582480000,5.024755,8.626485 742 2023-04-06 23:41:28,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-allhead,224000000,5.026874,22.441402 743 2023-04-06 23:41:33,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--stack-insfirst-remelem,534009000,5.029006,9.417456 744 2023-04-06 23:41:38,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--queue-inslast-remelem,159326200,5.174692,32.478601 745 2023-04-06 23:41:43,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--stack-insfirst-remelem,784000000,5.004447,6.383223 746 2023-04-06 23:41:48,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-remelem,224000000,5.007044,22.352875 747 2023-04-06 23:41:53,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-allhead,166568300,5.093894,30.581413 748 2023-04-06 23:41:58,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--stack-inslast-inselem,501580000,5.063699,10.095496 749 2023-04-06 23:42:03,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--stack-insfirst-inselem,672000000,5.002208,7.443762 750 2023-04-06 23:42:09,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--stack-inslast-allhead,700000000,5.035791,7.193987 751 2023-04-06 23:42:14,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--stack-inslast-remelem,1263800000,5.028343,3.978749 752 2023-04-06 23:42:19,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--queue-inslast-remelem,159326200,5.113131,32.092217 753 2023-04-06 23:42:24,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--stack-inslast-remelem,597366000,5.046347,8.447664 754 2023-04-06 23:42:29,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--queue-insfirst-remelem,642621000,5.053251,7.863501 755 2023-04-06 23:42:34,4,5 10000 809 -1 4 ,./perfexp--upp-upp--stack-inslast-inselem,444950000,5.077268,11.410873 756 2023-04-06 23:42:39,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--queue-inslast-inselem,171969000,5.099023,29.650827 757 2023-04-06 23:42:44,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--stack-inslast-allhead,325836000,5.047047,15.489532 758 2023-04-06 23:42:49,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-allhead,181020000,5.216122,28.815170 759 2023-04-06 23:42:54,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-allhead,181020000,5.222584,28.850867 760 2023-04-06 23:43:00,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--queue-inslast-remelem,534009000,5.024676,9.409347 761 2023-04-06 23:43:05,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-allhead,162918000,5.066455,31.098191 762 2023-04-06 23:43:10,4,5 100000 71 -1 4 ,./perfexp--upp-upp--stack-inslast-allhead,646100000,5.006395,7.748638 763 2023-04-06 23:43:15,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--stack-inslast-allhead,1022400000,5.033839,4.923551 764 2023-04-06 23:43:20,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-remelem,169890000,5.194201,30.573907 765 2023-04-06 23:43:25,3,5 100000 71 -1 3 ,./perfexp--upp-upp--stack-insfirst-inselem,617700000,5.004354,8.101593 766 2023-04-06 23:43:30,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-inselem,568000000,5.053840,8.897606 767 2023-04-06 23:43:35,4,5 100000 71 -1 4 ,./perfexp--lq-tailq--queue-inslast-allhead,773900000,5.009564,6.473141 768 2023-04-06 23:43:40,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-inselem,477310000,5.060300,10.601705 769 2023-04-06 23:43:45,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-remelem,766800000,5.029327,6.558851 770 2023-04-06 23:43:50,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--stack-insfirst-inselem,307734000,5.015156,16.297049 771 2023-04-06 23:43:55,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-allhead,343938000,5.030864,14.627241 772 2023-04-06 23:44:00,1,5 100000 71 -1 1 ,./perfexp--upp-upp--stack-inslast-inselem,546700000,5.028823,9.198506 773 2023-04-06 23:44:06,4,5 100 72421 -1 4 ,./perfexp--upp-upp--stack-insfirst-allhead,159326200,5.159831,32.385326 774 2023-04-06 23:44:11,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-inselem,184600000,5.013750,27.160076 775 2023-04-06 23:44:16,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--stack-inslast-remelem,184600000,5.191165,28.121154 776 2023-04-06 23:44:21,3,5 100 72421 -1 3 ,./perfexp--lq-list--stack-insfirst-inselem,166568300,5.221509,31.347555 777 2023-04-06 23:44:26,1,5 100000 71 -1 1 ,./perfexp--lq-list--stack-insfirst-remelem,681600000,5.027947,7.376683 778 2023-04-06 23:44:31,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--queue-inslast-allhead,493490000,5.065787,10.265227 779 2023-04-06 23:44:36,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--stack-inslast-inselem,448000000,5.071891,11.321185 780 2023-04-06 23:44:41,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--stack-inslast-remelem,570213000,5.041445,8.841336 781 2023-04-06 23:44:46,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-inselem,224000000,5.075413,22.658094 782 2023-04-06 23:44:51,1,5 10000 809 -1 1 ,./perfexp--upp-upp--stack-insfirst-allhead,517760000,5.074958,9.801758 783 2023-04-06 23:44:57,1,5 1000 9051 -1 1 ,./perfexp--lq-list--stack-insfirst-inselem,325836000,5.079069,15.587808 784 2023-04-06 23:45:02,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--stack-inslast-remelem,184600000,5.156223,27.931869 785 2023-04-06 23:45:07,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--queue-inslast-remelem,646100000,5.048818,7.814298 786 2023-04-06 23:45:12,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-remelem,153867000,5.084243,33.043102 787 2023-04-06 23:45:17,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-remelem,152084100,5.088762,33.460184 788 2023-04-06 23:45:22,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-inselem,477310000,5.040919,10.561101 789 2023-04-06 23:45:27,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-allhead,166568300,5.107945,30.665769 790 2023-04-06 23:45:32,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-remelem,759700000,5.013032,6.598699 791 2023-04-06 23:45:37,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-inselem,159326200,5.183840,32.536017 792 2023-04-06 23:45:43,2,5 100000 71 -1 2 ,./perfexp--upp-upp--stack-inslast-inselem,546700000,5.060570,9.256576 793 2023-04-06 23:45:48,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-remelem,773900000,5.016882,6.482597 794 2023-04-06 23:45:53,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--queue-inslast-allhead,137599900,5.146936,37.405085 795 2023-04-06 23:45:58,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-inselem,665000000,5.030136,7.564114 796 2023-04-06 23:46:03,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-allhead,231000000,5.069341,21.945199 797 2023-04-06 23:46:08,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--queue-inslast-remelem,588315000,5.038815,8.564825 798 2023-04-06 23:46:13,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--stack-inslast-remelem,597366000,5.062109,8.474049 799 2023-04-06 23:46:18,5,5 100 72421 -1 5 ,./perfexp--upp-upp--queue-insfirst-allhead,130357800,5.097324,39.102562 800 2023-04-06 23:46:23,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-inselem,181020000,5.245083,28.975157 801 2023-04-06 23:46:28,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--stack-inslast-remelem,728100000,5.048765,6.934164 802 2023-04-06 23:46:34,2,5 100 72421 -1 2 ,./perfexp--upp-upp--queue-inslast-remelem,260715600,5.006853,19.204271 803 2023-04-06 23:46:39,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--queue-inslast-remelem,171969000,5.222348,30.367962 804 2023-04-06 23:46:44,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-remelem,917000000,5.014479,5.468352 805 2023-04-06 23:46:49,4,5 100 72421 -1 4 ,./perfexp--lq-list--stack-insfirst-inselem,166568300,5.223544,31.359773 806 2023-04-06 23:46:54,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--stack-inslast-allhead,994000000,5.008805,5.039039 807 2023-04-06 23:46:59,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--stack-inslast-allhead,509670000,5.037473,9.883793 808 2023-04-06 23:47:04,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-allhead,444950000,5.008930,11.257287 809 2023-04-06 23:47:09,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--stack-inslast-remelem,1022400000,5.031635,4.921396 810 2023-04-06 23:47:14,1,5 1000000 7 -1 1 ,./perfexp--lq-list--stack-insfirst-remelem,798000000,5.019472,6.290065 811 2023-04-06 23:47:19,1,5 100 72421 -1 1 ,./perfexp--lq-list--stack-insfirst-remelem,333136600,5.086682,15.269058 812 2023-04-06 23:47:24,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-inselem,444950000,5.009886,11.259436 813 2023-04-06 23:47:29,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--queue-insfirst-allhead,1022000000,5.028409,4.920165 814 2023-04-06 23:47:34,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--stack-inslast-inselem,224000000,5.134726,22.922884 815 2023-04-06 23:47:40,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--stack-insfirst-allhead,166568300,5.129354,30.794299 816 2023-04-06 23:47:45,3,5 100 72421 -1 3 ,./perfexp--upp-upp--stack-insfirst-remelem,267957700,5.029663,18.770362 817 2023-04-06 23:47:50,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--queue-inslast-allhead,144842000,5.159035,35.618363 818 2023-04-06 23:47:55,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--stack-inslast-remelem,153867000,5.205434,33.830737 819 2023-04-06 23:48:00,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--queue-insfirst-remelem,859100000,5.024798,5.848909 820 2023-04-06 23:48:05,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--queue-inslast-inselem,352989000,5.106726,14.467097 821 2023-04-06 23:48:10,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--queue-inslast-inselem,325836000,5.095977,15.639699 822 2023-04-06 23:48:15,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-inselem,162918000,5.237821,32.150045 823 2023-04-06 23:48:21,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--stack-inslast-allhead,231000000,5.106340,22.105368 824 2023-04-06 23:48:26,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--queue-inslast-inselem,159326200,5.099221,32.004912 825 2023-04-06 23:48:31,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--stack-insfirst-inselem,159326200,5.004885,31.412818 826 2023-04-06 23:48:36,2,5 100 72421 -1 2 ,./perfexp--upp-upp--queue-insfirst-inselem,130357800,5.103887,39.152908 827 2023-04-06 23:48:41,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--queue-insfirst-allhead,316785000,5.095627,16.085443 828 2023-04-06 23:48:46,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--stack-inslast-allhead,169890000,5.023940,29.571723 829 2023-04-06 23:48:51,3,5 100000 71 -1 3 ,./perfexp--lq-list--stack-insfirst-inselem,724200000,5.040016,6.959426 830 2023-04-06 23:48:56,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--queue-insfirst-allhead,679000000,5.039133,7.421404 831 2023-04-06 23:49:01,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--stack-inslast-remelem,159326200,5.202599,32.653757 832 2023-04-06 23:49:07,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--queue-insfirst-allhead,316785000,5.001730,15.789037 833 2023-04-06 23:49:12,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--stack-inslast-remelem,224000000,5.005996,22.348196 834 2023-04-06 23:49:17,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--queue-inslast-allhead,672000000,5.047250,7.510789 835 2023-04-06 23:49:22,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--queue-inslast-inselem,710000000,5.015764,7.064456 836 2023-04-06 23:49:27,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--queue-insfirst-remelem,642621000,5.038532,7.840597 837 2023-04-06 23:49:32,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-remelem,152084100,5.074580,33.366933 838 2023-04-06 23:49:37,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-allhead,169890000,5.038720,29.658720 839 2023-04-06 23:49:42,3,5 100 72421 -1 3 ,./perfexp--upp-upp--queue-insfirst-allhead,130357800,5.097956,39.107411 840 2023-04-06 23:49:47,2,5 1000000 7 -1 2 ,./perfexp--cfa-cfa--queue-inslast-allhead,665000000,5.003770,7.524466 841 2023-04-06 23:49:52,5,5 100000 71 -1 5 ,./perfexp--upp-upp--queue-inslast-inselem,646100000,5.033712,7.790918 842 2023-04-06 23:49:57,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--stack-inslast-remelem,159326200,5.197406,32.621163 843 2023-04-06 23:50:02,3,5 1000000 7 -1 3 ,./perfexp--lq-list--stack-insfirst-remelem,798000000,5.021226,6.292263 844 2023-04-06 23:50:07,2,5 100 72421 -1 2 ,./perfexp--upp-upp--stack-insfirst-remelem,267957700,5.036691,18.796590 845 2023-04-06 23:50:12,5,5 10000 809 -1 5 ,./perfexp--lq-list--stack-insfirst-allhead,517760000,5.076458,9.804655 846 2023-04-06 23:50:18,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-inselem,343938000,5.111457,14.861565 847 2023-04-06 23:50:23,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--queue-inslast-remelem,766800000,5.036608,6.568346 848 2023-04-06 23:50:28,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--stack-inslast-allhead,639000000,5.008767,7.838446 849 2023-04-06 23:50:33,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-inselem,343938000,5.096478,14.818014 850 2023-04-06 23:50:38,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--queue-inslast-inselem,224000000,5.053022,22.558134 851 2023-04-06 23:50:43,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--stack-inslast-inselem,588000000,5.043254,8.576963 852 2023-04-06 23:50:48,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--queue-insfirst-allhead,325836000,5.142199,15.781556 853 2023-04-06 23:50:53,3,5 100000 71 -1 3 ,./perfexp--upp-upp--queue-inslast-inselem,575100000,5.013201,8.717094 854 2023-04-06 23:50:58,1,5 100000 71 -1 1 ,./perfexp--upp-upp--stack-insfirst-allhead,788100000,5.011622,6.359119 855 2023-04-06 23:51:03,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-inselem,603500000,5.049321,8.366729 856 2023-04-06 23:51:08,2,5 100 72421 -1 2 ,./perfexp--lq-list--stack-insfirst-allhead,166568300,5.050434,30.320499 857 2023-04-06 23:51:13,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-inselem,162918000,5.096707,31.283879 858 2023-04-06 23:51:18,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--stack-insfirst-allhead,805000000,5.003890,6.216012 859 2023-04-06 23:51:23,1,5 100 72421 -1 1 ,./perfexp--upp-upp--queue-inslast-inselem,137599900,5.089424,36.987120 860 2023-04-06 23:51:29,5,5 10000 809 -1 5 ,./perfexp--lq-list--stack-insfirst-remelem,582480000,5.006380,8.594939 861 2023-04-06 23:51:34,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--queue-inslast-allhead,453040000,5.016531,11.073042 862 2023-04-06 23:51:39,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--queue-inslast-inselem,453040000,5.063734,11.177234 863 2023-04-06 23:51:44,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-allhead,177980000,5.226280,29.364423 864 2023-04-06 23:51:49,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--queue-inslast-allhead,343938000,5.057972,14.706057 865 2023-04-06 23:51:54,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--stack-insfirst-allhead,509670000,5.025430,9.860164 866 2023-04-06 23:51:59,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--stack-inslast-remelem,161800000,5.000954,30.908245 867 2023-04-06 23:52:04,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-allhead,181020000,5.211717,28.790835 868 2023-04-06 23:52:09,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--stack-inslast-allhead,477310000,5.049791,10.579688 869 2023-04-06 23:52:14,1,5 10000 809 -1 1 ,./perfexp--lq-list--stack-insfirst-remelem,590570000,5.016456,8.494261 870 2023-04-06 23:52:19,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--queue-insfirst-remelem,534009000,5.061113,9.477580 871 2023-04-06 23:52:24,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-remelem,169890000,5.017420,29.533345 872 2023-04-06 23:52:29,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--queue-inslast-inselem,485400000,5.081081,10.467822 873 2023-04-06 23:52:34,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-allhead,343938000,5.033256,14.634196 874 2023-04-06 23:52:40,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--queue-inslast-remelem,784000000,5.033145,6.419828 875 2023-04-06 23:52:45,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--stack-inslast-inselem,980000000,5.012630,5.114929 876 2023-04-06 23:52:50,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--stack-insfirst-remelem,791000000,5.040982,6.372923 877 2023-04-06 23:52:55,2,5 10000 809 -1 2 ,./perfexp--upp-upp--stack-inslast-inselem,444950000,5.091346,11.442513 878 2023-04-06 23:53:00,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--queue-inslast-remelem,752600000,5.007532,6.653643 879 2023-04-06 23:53:05,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-remelem,171969000,5.137818,29.876420 880 2023-04-06 23:53:10,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--stack-inslast-allhead,477310000,5.056730,10.594226 881 2023-04-06 23:53:15,3,5 100000 71 -1 3 ,./perfexp--upp-upp--queue-insfirst-inselem,539600000,5.044061,9.347778 882 2023-04-06 23:53:20,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--queue-inslast-allhead,889000000,5.018817,5.645463 883 2023-04-06 23:53:25,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--queue-inslast-allhead,485400000,5.004149,10.309330 884 2023-04-06 23:53:30,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--stack-inslast-remelem,687876000,5.062201,7.359177 885 2023-04-06 23:53:35,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-allhead,137599900,5.148068,37.413312 886 2023-04-06 23:53:40,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--queue-insfirst-inselem,289632000,5.012993,17.308146 887 2023-04-06 23:53:45,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--queue-inslast-inselem,575100000,5.045375,8.773039 888 2023-04-06 23:53:50,1,5 100 72421 -1 1 ,./perfexp--upp-upp--queue-insfirst-allhead,130357800,5.099296,39.117690 889 2023-04-06 23:53:56,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--stack-inslast-inselem,588000000,5.037787,8.567665 890 2023-04-06 23:54:01,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-allhead,184600000,5.105671,27.658023 891 2023-04-06 23:54:06,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--stack-insfirst-remelem,333136600,5.074849,15.233538 892 2023-04-06 23:54:11,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--stack-inslast-remelem,325894500,5.093924,15.630592 893 2023-04-06 23:54:16,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-allhead,343938000,5.031887,14.630215 894 2023-04-06 23:54:21,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--stack-inslast-remelem,965600000,5.024737,5.203746 895 2023-04-06 23:54:26,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--stack-insfirst-allhead,343938000,5.000385,14.538623 896 2023-04-06 23:54:31,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--stack-inslast-allhead,162918000,5.114478,31.392958 897 2023-04-06 23:54:36,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--queue-inslast-remelem,784000000,5.034203,6.421177 898 2023-04-06 23:54:41,2,5 100000 71 -1 2 ,./perfexp--lq-list--stack-insfirst-allhead,773900000,5.039677,6.512052 899 2023-04-06 23:54:46,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--stack-inslast-remelem,325894500,5.097422,15.641326 900 2023-04-06 23:54:51,2,5 1000000 7 -1 2 ,./perfexp--upp-upp--stack-insfirst-remelem,756000000,5.023632,6.645016 901 2023-04-06 23:54:56,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--queue-inslast-remelem,695740000,5.045478,7.251959 902 2023-04-06 23:55:01,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--queue-inslast-remelem,177500000,5.031516,28.346569 903 2023-04-06 23:55:07,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-allhead,159326200,5.042017,31.645875 904 2023-04-06 23:55:12,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-allhead,343938000,5.028640,14.620775 905 2023-04-06 23:55:17,5,5 10000 809 -1 5 ,./perfexp--upp-upp--queue-inslast-inselem,444950000,5.013986,11.268650 906 2023-04-06 23:55:22,5,5 100 72421 -1 5 ,./perfexp--upp-upp--stack-insfirst-remelem,267957700,5.032008,18.779113 907 2023-04-06 23:55:27,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--queue-inslast-allhead,352989000,5.053183,14.315412 908 2023-04-06 23:55:32,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-inselem,159326200,5.186497,32.552694 909 2023-04-06 23:55:37,2,5 1000 9051 -1 2 ,./perfexp--lq-list--stack-insfirst-remelem,534009000,5.014736,9.390733 910 2023-04-06 23:55:42,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--queue-inslast-remelem,534009000,5.029801,9.418944 911 2023-04-06 23:55:47,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--stack-inslast-inselem,343938000,5.069517,14.739625 912 2023-04-06 23:55:52,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--queue-inslast-allhead,582200000,5.043558,8.662930 913 2023-04-06 23:55:57,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-remelem,184600000,5.143890,27.865060 914 2023-04-06 23:56:02,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--queue-inslast-allhead,461130000,5.080796,11.018142 915 2023-04-06 23:56:07,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--queue-inslast-inselem,171969000,5.118993,29.766952 916 2023-04-06 23:56:13,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--queue-insfirst-remelem,720010000,5.035548,6.993720 917 2023-04-06 23:56:18,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-inselem,137599900,5.147075,37.406095 918 2023-04-06 23:56:23,3,5 10000 809 -1 3 ,./perfexp--upp-upp--stack-insfirst-remelem,582480000,5.029466,8.634573 919 2023-04-06 23:56:28,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--stack-inslast-allhead,166568300,5.213374,31.298717 920 2023-04-06 23:56:33,4,5 100 72421 -1 4 ,./perfexp--upp-upp--queue-insfirst-inselem,130357800,5.104179,39.155148 921 2023-04-06 23:56:38,5,5 10000 809 -1 5 ,./perfexp--upp-upp--queue-insfirst-remelem,647200000,5.055149,7.810799 922 2023-04-06 23:56:43,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-allhead,334887000,5.047137,15.071164 923 2023-04-06 23:56:48,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--queue-insfirst-inselem,973000000,5.030706,5.170304 924 2023-04-06 23:56:53,5,5 100 72421 -1 5 ,./perfexp--upp-upp--stack-insfirst-inselem,159326200,5.197585,32.622287 925 2023-04-06 23:56:59,5,5 10000 809 -1 5 ,./perfexp--upp-upp--queue-insfirst-allhead,444950000,5.057074,11.365488 926 2023-04-06 23:57:04,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--queue-inslast-remelem,177500000,5.028745,28.330958 927 2023-04-06 23:57:09,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--queue-insfirst-allhead,325836000,5.133705,15.755487 928 2023-04-06 23:57:14,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-inselem,181020000,5.216624,28.817943 929 2023-04-06 23:57:19,5,5 100000 71 -1 5 ,./perfexp--upp-upp--queue-insfirst-inselem,546700000,5.040683,9.220199 930 2023-04-06 23:57:24,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--stack-insfirst-allhead,166568300,5.126525,30.777315 931 2023-04-06 23:57:29,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--queue-inslast-allhead,752600000,5.030341,6.683950 932 2023-04-06 23:57:34,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--queue-insfirst-inselem,781000000,5.002303,6.404997 933 2023-04-06 23:57:39,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--queue-inslast-remelem,311410300,5.110663,16.411349 934 2023-04-06 23:57:44,5,5 100 72421 -1 5 ,./perfexp--upp-upp--queue-inslast-remelem,260715600,5.004443,19.195027 935 2023-04-06 23:57:49,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-inselem,177980000,5.040817,28.322379 936 2023-04-06 23:57:55,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--queue-inslast-remelem,777000000,5.012582,6.451199 937 2023-04-06 23:58:00,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--queue-insfirst-inselem,130357800,5.143872,39.459641 938 2023-04-06 23:58:05,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-remelem,588315000,5.034068,8.556756 939 2023-04-06 23:58:10,1,5 10000 809 -1 1 ,./perfexp--upp-upp--queue-inslast-inselem,436860000,5.006743,11.460749 940 2023-04-06 23:58:15,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--stack-insfirst-inselem,159326200,5.004273,31.408977 941 2023-04-06 23:58:20,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--stack-insfirst-remelem,784000000,5.042812,6.432158 942 2023-04-06 23:58:25,5,5 100000 71 -1 5 ,./perfexp--lq-list--stack-insfirst-allhead,788100000,5.002504,6.347550 943 2023-04-06 23:58:30,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-inselem,177500000,5.009520,28.222648 944 2023-04-06 23:58:35,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--stack-inslast-allhead,162918000,5.140808,31.554573 945 2023-04-06 23:58:40,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--queue-inslast-inselem,144842000,5.151509,35.566403 946 2023-04-06 23:58:45,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--stack-inslast-remelem,152084100,5.034474,33.103224 947 2023-04-06 23:58:50,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--stack-insfirst-inselem,184600000,5.137038,27.827941 948 2023-04-06 23:58:56,5,5 10000 809 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-inselem,477310000,5.038631,10.556307 949 2023-04-06 23:59:01,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--queue-inslast-inselem,171969000,5.114824,29.742709 950 2023-04-06 23:59:06,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--queue-inslast-remelem,515907000,5.030354,9.750505 951 2023-04-06 23:59:11,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-allhead,665000000,5.014697,7.540898 952 2023-04-06 23:59:16,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-allhead,665000000,5.003080,7.523429 953 2023-04-06 23:59:21,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-allhead,169890000,5.029569,29.604856 954 2023-04-06 23:59:26,3,5 100000 71 -1 3 ,./perfexp--upp-upp--stack-insfirst-allhead,724200000,5.029829,6.945359 955 2023-04-06 23:59:31,1,5 10000 809 -1 1 ,./perfexp--upp-upp--queue-inslast-allhead,493490000,5.010267,10.152722 956 2023-04-06 23:59:36,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--stack-inslast-remelem,153867000,5.204054,33.821768 957 2023-04-06 23:59:41,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--stack-insfirst-inselem,159326200,5.006861,31.425221 958 2023-04-06 23:59:46,5,5 100 72421 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-inselem,166568300,5.134474,30.825037 959 2023-04-06 23:59:51,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-allhead,177500000,5.021209,28.288501 960 2023-04-06 23:59:56,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--queue-inslast-remelem,959000000,5.000634,5.214425 961 2023-04-07 00:00:01,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--queue-inslast-allhead,177980000,5.123476,28.786808 962 2023-04-07 00:00:07,5,5 10000 809 -1 5 ,./perfexp--upp-upp--stack-insfirst-remelem,574390000,5.003850,8.711590 963 2023-04-07 00:00:12,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--stack-inslast-remelem,678825000,5.004920,7.372916 964 2023-04-07 00:00:17,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--queue-insfirst-inselem,788100000,5.031101,6.383836 965 2023-04-07 00:00:22,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--stack-inslast-allhead,334887000,5.030583,15.021733 966 2023-04-07 00:00:27,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--queue-insfirst-inselem,298683000,5.139339,17.206667 967 2023-04-07 00:00:32,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-allhead,485400000,5.084587,10.475045 968 2023-04-07 00:00:37,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--queue-inslast-remelem,590570000,5.043516,8.540082 969 2023-04-07 00:00:42,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-allhead,231000000,5.119258,22.161290 970 2023-04-07 00:00:47,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--stack-insfirst-remelem,461601000,5.024322,10.884556 971 2023-04-07 00:00:52,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--queue-insfirst-allhead,461130000,5.076500,11.008826 972 2023-04-07 00:00:57,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--queue-insfirst-inselem,588000000,5.001611,8.506141 973 2023-04-07 00:01:02,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-inselem,169890000,5.145494,30.287209 974 2023-04-07 00:01:07,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--stack-inslast-allhead,672000000,5.044544,7.506762 975 2023-04-07 00:01:12,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--stack-insfirst-remelem,534009000,5.004349,9.371282 976 2023-04-07 00:01:17,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--stack-inslast-inselem,987000000,5.025173,5.091361 977 2023-04-07 00:01:23,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--stack-inslast-remelem,169890000,5.236716,30.824157 978 2023-04-07 00:01:28,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-allhead,334887000,5.055747,15.096874 979 2023-04-07 00:01:33,2,5 1000000 7 -1 2 ,./perfexp--lq-list--stack-insfirst-allhead,924000000,5.034723,5.448834 980 2023-04-07 00:01:38,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--queue-insfirst-remelem,296926100,5.111804,17.215745 981 2023-04-07 00:01:43,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--stack-inslast-remelem,325894500,5.092882,15.627395 982 2023-04-07 00:01:48,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--stack-inslast-inselem,493490000,5.012330,10.156903 983 2023-04-07 00:01:53,1,5 100000 71 -1 1 ,./perfexp--upp-upp--queue-insfirst-allhead,660300000,5.052296,7.651516 984 2023-04-07 00:01:58,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--stack-insfirst-inselem,169890000,5.023551,29.569433 985 2023-04-07 00:02:03,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--stack-inslast-inselem,162918000,5.065419,31.091831 986 2023-04-07 00:02:08,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--stack-inslast-inselem,159326200,5.065417,31.792743 987 2023-04-07 00:02:13,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-inselem,610600000,5.045429,8.263067 988 2023-04-07 00:02:18,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-remelem,159326200,5.086272,31.923638 989 2023-04-07 00:02:24,1,5 100000 71 -1 1 ,./perfexp--upp-upp--queue-insfirst-remelem,773900000,5.011786,6.476012 990 2023-04-07 00:02:29,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--queue-inslast-remelem,695740000,5.035083,7.237018 991 2023-04-07 00:02:34,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-inselem,617700000,5.034056,8.149678 992 2023-04-07 00:02:39,2,5 1000 9051 -1 2 ,./perfexp--lq-tailq--queue-insfirst-allhead,316785000,5.101400,16.103667 993 2023-04-07 00:02:44,4,5 100000 71 -1 4 ,./perfexp--upp-upp--queue-insfirst-allhead,624800000,5.004312,8.009462 994 2023-04-07 00:02:49,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--queue-insfirst-inselem,444950000,5.086458,11.431527 995 2023-04-07 00:02:54,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-inselem,343938000,5.095479,14.815109 996 2023-04-07 00:02:59,3,5 10000 809 -1 3 ,./perfexp--upp-upp--stack-inslast-allhead,501580000,5.078669,10.125342 997 2023-04-07 00:03:04,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--stack-inslast-allhead,325836000,5.035838,15.455131 998 2023-04-07 00:03:09,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--queue-insfirst-remelem,642621000,5.048161,7.855581 999 2023-04-07 00:03:14,5,5 1000 9051 -1 5 ,./perfexp--lq-list--stack-insfirst-allhead,343938000,5.068172,14.735714 1000 2023-04-07 00:03:19,2,5 10000 809 -1 2 ,./perfexp--lq-list--stack-insfirst-allhead,509670000,5.010027,9.829943 1001 2023-04-07 00:03:24,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--queue-insfirst-remelem,711920000,5.004285,7.029280 1002 2023-04-07 00:03:29,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--queue-inslast-inselem,343938000,5.124094,14.898307 1003 2023-04-07 00:03:35,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-remelem,289684000,5.109375,17.637754 1004 2023-04-07 00:03:40,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--queue-inslast-inselem,177980000,5.226474,29.365513 1005 2023-04-07 00:03:45,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--stack-inslast-remelem,1421000000,5.024039,3.535566 1006 2023-04-07 00:03:50,3,5 100 72421 -1 3 ,./perfexp--upp-upp--queue-inslast-allhead,137599900,5.041139,36.636211 1007 2023-04-07 00:03:55,4,5 100 72421 -1 4 ,./perfexp--upp-upp--stack-inslast-allhead,159326200,5.081520,31.893813 1008 2023-04-07 00:04:00,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--stack-insfirst-inselem,581000000,5.046014,8.685050 1009 2023-04-07 00:04:05,5,5 10000 809 -1 5 ,./perfexp--upp-upp--stack-inslast-allhead,493490000,5.016015,10.164370 1010 2023-04-07 00:04:10,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--stack-insfirst-inselem,581000000,5.003459,8.611806 1011 2023-04-07 00:04:15,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--queue-inslast-inselem,693000000,5.001641,7.217375 1012 2023-04-07 00:04:20,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--stack-inslast-allhead,159326200,5.162225,32.400352 1013 2023-04-07 00:04:25,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--stack-inslast-remelem,325894500,5.086104,15.606597 1014 2023-04-07 00:04:31,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--queue-insfirst-inselem,307734000,5.019841,16.312273 1015 2023-04-07 00:04:36,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--stack-inslast-allhead,469220000,5.001562,10.659311 1016 2023-04-07 00:04:41,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--queue-insfirst-inselem,130357800,5.142624,39.450067 1017 2023-04-07 00:04:46,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-allhead,553800000,5.013626,9.053135 1018 2023-04-07 00:04:51,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--stack-insfirst-remelem,333136600,5.076545,15.238629 1019 2023-04-07 00:04:56,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--stack-inslast-inselem,169890000,5.071793,29.853393 1020 2023-04-07 00:05:01,3,5 10000 809 -1 3 ,./perfexp--upp-upp--queue-inslast-allhead,501580000,5.064339,10.096772 1021 2023-04-07 00:05:06,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-remelem,153867000,5.176563,33.643101 1022 2023-04-07 00:05:11,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-allhead,184600000,5.032819,27.263375 1023 2023-04-07 00:05:16,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-remelem,224000000,5.024146,22.429223 1024 2023-04-07 00:05:21,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--queue-inslast-remelem,588315000,5.050261,8.584281 1025 2023-04-07 00:05:26,5,5 1000000 7 -1 5 ,./perfexp--cfa-cfa--queue-inslast-remelem,980000000,5.025545,5.128107 1026 2023-04-07 00:05:32,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-inselem,166568300,5.065528,30.411117 1027 2023-04-07 00:05:37,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-remelem,318652400,5.015438,15.739527 1028 2023-04-07 00:05:42,4,5 100000 71 -1 4 ,./perfexp--upp-upp--stack-inslast-remelem,823600000,5.033144,6.111151 1029 2023-04-07 00:05:47,1,5 100000 71 -1 1 ,./perfexp--upp-upp--queue-inslast-allhead,710000000,5.007572,7.052918 1030 2023-04-07 00:05:52,3,5 100 72421 -1 3 ,./perfexp--upp-upp--queue-insfirst-inselem,130357800,5.098879,39.114491 1031 2023-04-07 00:05:57,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--queue-inslast-allhead,166568300,5.181296,31.106135 1032 2023-04-07 00:06:02,2,5 100 72421 -1 2 ,./perfexp--upp-upp--stack-insfirst-inselem,159326200,5.206496,32.678216 1033 2023-04-07 00:06:07,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--stack-insfirst-remelem,333136600,5.083054,15.258167 1034 2023-04-07 00:06:12,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--queue-inslast-inselem,159326200,5.023020,31.526642 1035 2023-04-07 00:06:17,5,5 10000 809 -1 5 ,./perfexp--upp-upp--stack-insfirst-inselem,477310000,5.066548,10.614795 1036 2023-04-07 00:06:23,4,5 10000 809 -1 4 ,./perfexp--upp-upp--queue-inslast-inselem,444950000,5.002215,11.242196 1037 2023-04-07 00:06:28,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--queue-insfirst-allhead,731300000,5.007529,6.847435 1038 2023-04-07 00:06:33,5,5 1000 9051 -1 5 ,./perfexp--lq-tailq--stack-insfirst-inselem,316785000,5.004748,15.798564 1039 2023-04-07 00:06:38,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--stack-inslast-inselem,588000000,5.046407,8.582325 1040 2023-04-07 00:06:43,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-remelem,917000000,5.029605,5.484847 1041 2023-04-07 00:06:48,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--queue-inslast-inselem,833000000,5.018035,6.024052 1042 2023-04-07 00:06:53,4,5 10000 809 -1 4 ,./perfexp--upp-upp--stack-insfirst-allhead,525850000,5.070215,9.641942 1043 2023-04-07 00:06:58,5,5 100000 71 -1 5 ,./perfexp--upp-upp--stack-insfirst-remelem,731300000,5.028043,6.875486 1044 2023-04-07 00:07:03,5,5 10000 809 -1 5 ,./perfexp--upp-upp--queue-inslast-remelem,614840000,5.028645,8.178786 1045 2023-04-07 00:07:08,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--stack-inslast-remelem,720010000,5.048400,7.011569 1046 2023-04-07 00:07:13,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--stack-inslast-remelem,224000000,5.107446,22.801098 1047 2023-04-07 00:07:18,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--queue-inslast-allhead,959000000,5.009608,5.223783 1048 2023-04-07 00:07:23,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-remelem,184600000,5.136296,27.823922 1049 2023-04-07 00:07:28,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--queue-inslast-remelem,695740000,5.019980,7.215310 1050 2023-04-07 00:07:33,4,5 10000 809 -1 4 ,./perfexp--upp-upp--queue-inslast-allhead,493490000,5.031048,10.194833 1051 2023-04-07 00:07:38,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--queue-insfirst-remelem,534009000,5.044507,9.446483 1052 2023-04-07 00:07:43,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--stack-inslast-inselem,343938000,5.079265,14.767967 1053 2023-04-07 00:07:48,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--queue-inslast-inselem,568000000,5.039315,8.872033 1054 2023-04-07 00:07:53,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--queue-insfirst-inselem,436860000,5.036864,11.529698 1055 2023-04-07 00:07:58,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--queue-inslast-inselem,724200000,5.004672,6.910621 1056 2023-04-07 00:08:03,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--stack-inslast-inselem,159326200,5.152197,32.337412 1057 2023-04-07 00:08:09,4,5 100 72421 -1 4 ,./perfexp--upp-upp--queue-inslast-allhead,137599900,5.043725,36.655005 1058 2023-04-07 00:08:14,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--stack-insfirst-remelem,461601000,5.010361,10.854311 1059 2023-04-07 00:08:19,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-allhead,444950000,5.008312,11.255898 1060 2023-04-07 00:08:24,5,5 100000 71 -1 5 ,./perfexp--upp-upp--queue-insfirst-allhead,646100000,5.052912,7.820635 1061 2023-04-07 00:08:29,3,5 1000000 7 -1 3 ,./perfexp--upp-upp--queue-inslast-inselem,693000000,5.024033,7.249687 1062 2023-04-07 00:08:34,5,5 1000 9051 -1 5 ,./perfexp--cpp-stlref--queue-inslast-inselem,171969000,5.113559,29.735353 1063 2023-04-07 00:08:39,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--queue-inslast-remelem,224000000,5.136808,22.932179 1064 2023-04-07 00:08:44,2,5 1000000 7 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-allhead,224000000,5.087099,22.710263 1065 2023-04-07 00:08:49,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--queue-inslast-inselem,693000000,5.001977,7.217860 1066 2023-04-07 00:08:54,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--stack-insfirst-allhead,325836000,5.086269,15.609905 1067 2023-04-07 00:08:59,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-remelem,152084100,5.070523,33.340257 1068 2023-04-07 00:09:04,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--stack-insfirst-inselem,307734000,5.001254,16.251873 1069 2023-04-07 00:09:09,3,5 1000 9051 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-inselem,181020000,5.244969,28.974528 1070 2023-04-07 00:09:15,3,5 100 72421 -1 3 ,./perfexp--upp-upp--stack-inslast-allhead,159326200,5.076574,31.862770 1071 2023-04-07 00:09:20,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-allhead,560900000,5.015707,8.942248 1072 2023-04-07 00:09:25,1,5 100000 71 -1 1 ,./perfexp--upp-upp--stack-inslast-remelem,937200000,5.038076,5.375668 1073 2023-04-07 00:09:30,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--queue-insfirst-inselem,177980000,5.087129,28.582588 1074 2023-04-07 00:09:35,4,5 10000 809 -1 4 ,./perfexp--lq-list--stack-insfirst-remelem,590570000,5.057216,8.563280 1075 2023-04-07 00:09:40,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--stack-inslast-inselem,159326200,5.148371,32.313399 1076 2023-04-07 00:09:45,1,5 1000 9051 -1 1 ,./perfexp--upp-upp--stack-insfirst-inselem,307734000,5.017681,16.305254 1077 2023-04-07 00:09:50,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-remelem,703830000,5.001011,7.105425 1078 2023-04-07 00:09:55,5,5 100 72421 -1 5 ,./perfexp--upp-upp--stack-inslast-inselem,159326200,5.146824,32.303689 1079 2023-04-07 00:10:00,4,5 100000 71 -1 4 ,./perfexp--lq-list--stack-insfirst-inselem,560900000,5.037575,8.981236 1080 2023-04-07 00:10:05,3,5 100 72421 -1 3 ,./perfexp--upp-upp--stack-insfirst-inselem,159326200,5.206990,32.681317 1081 2023-04-07 00:10:11,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--stack-inslast-inselem,177980000,5.212465,29.286802 1082 2023-04-07 00:10:16,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--queue-inslast-remelem,980000000,5.014558,5.116896 1083 2023-04-07 00:10:21,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--stack-insfirst-inselem,343938000,5.094368,14.811879 1084 2023-04-07 00:10:26,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-inselem,610600000,5.038606,8.251893 1085 2023-04-07 00:10:31,3,5 100000 71 -1 3 ,./perfexp--upp-upp--stack-insfirst-remelem,738400000,5.012787,6.788715 1086 2023-04-07 00:10:36,3,5 10000 809 -1 3 ,./perfexp--upp-upp--stack-inslast-remelem,679560000,5.029846,7.401622 1087 2023-04-07 00:10:41,2,5 10000 809 -1 2 ,./perfexp--upp-upp--queue-inslast-inselem,453040000,5.073771,11.199389 1088 2023-04-07 00:10:46,2,5 1000000 7 -1 2 ,./perfexp--lq-list--stack-insfirst-remelem,798000000,5.015579,6.285187 1089 2023-04-07 00:10:51,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--stack-inslast-inselem,493490000,5.060374,10.254258 1090 2023-04-07 00:10:56,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--queue-inslast-remelem,766800000,5.015732,6.541122 1091 2023-04-07 00:11:01,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--queue-inslast-inselem,453040000,5.070851,11.192943 1092 2023-04-07 00:11:06,2,5 10000 809 -1 2 ,./perfexp--upp-upp--stack-insfirst-allhead,509670000,5.009743,9.829386 1093 2023-04-07 00:11:11,2,5 100000 71 -1 2 ,./perfexp--upp-upp--queue-inslast-inselem,610600000,5.024440,8.228693 1094 2023-04-07 00:11:16,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--queue-inslast-allhead,759700000,5.040553,6.634926 1095 2023-04-07 00:11:21,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--stack-inslast-remelem,159326200,5.193180,32.594639 1096 2023-04-07 00:11:27,5,5 1000 9051 -1 5 ,./perfexp--cfa-cfa--queue-inslast-allhead,343938000,5.052484,14.690101 1097 2023-04-07 00:11:32,1,5 100000 71 -1 1 ,./perfexp--lq-list--stack-insfirst-allhead,788100000,5.016808,6.365700 1098 2023-04-07 00:11:37,2,5 100000 71 -1 2 ,./perfexp--upp-upp--queue-insfirst-allhead,660300000,5.045791,7.641664 1099 2023-04-07 00:11:42,4,5 100 72421 -1 4 ,./perfexp--upp-upp--stack-inslast-inselem,159326200,5.146330,32.300588 1100 2023-04-07 00:11:47,3,5 10000 809 -1 3 ,./perfexp--lq-list--stack-insfirst-allhead,509670000,5.049794,9.907968 1101 2023-04-07 00:11:52,1,5 100 72421 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-inselem,166568300,5.161840,30.989330 1102 2023-04-07 00:11:57,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--queue-insfirst-allhead,130357800,5.062710,38.837032 1103 2023-04-07 00:12:02,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--queue-inslast-inselem,159326200,5.089807,31.945826 1104 2023-04-07 00:12:08,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-remelem,282441900,5.058237,17.908947 1105 2023-04-07 00:12:13,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--queue-insfirst-remelem,224000000,5.036237,22.483201 1106 2023-04-07 00:12:18,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--stack-inslast-allhead,177500000,5.014610,28.251324 1107 2023-04-07 00:12:23,1,5 10000 809 -1 1 ,./perfexp--upp-upp--queue-insfirst-remelem,647200000,5.039386,7.786443 1108 2023-04-07 00:12:28,2,5 1000 9051 -1 2 ,./perfexp--lq-list--stack-insfirst-allhead,343938000,5.069521,14.739636 1109 2023-04-07 00:12:33,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-allhead,159326200,5.100854,32.015161 1110 2023-04-07 00:12:38,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--stack-insfirst-allhead,166568300,5.125007,30.768201 1111 2023-04-07 00:12:43,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--queue-insfirst-allhead,177980000,5.117398,28.752658 1112 2023-04-07 00:12:48,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--queue-inslast-remelem,590570000,5.052605,8.555472 1113 2023-04-07 00:12:53,4,5 1000 9051 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-allhead,343938000,5.025513,14.611683 1114 2023-04-07 00:12:58,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--queue-inslast-allhead,177980000,5.199746,29.215339 1115 2023-04-07 00:13:04,1,5 10000 809 -1 1 ,./perfexp--upp-upp--stack-inslast-remelem,679560000,5.058526,7.443825 1116 2023-04-07 00:13:09,2,5 100000 71 -1 2 ,./perfexp--upp-upp--queue-insfirst-remelem,710000000,5.003660,7.047408 1117 2023-04-07 00:13:14,2,5 100000 71 -1 2 ,./perfexp--upp-upp--queue-insfirst-inselem,560900000,5.048259,9.000283 1118 2023-04-07 00:13:19,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--stack-insfirst-allhead,896000000,5.014332,5.596353 1119 2023-04-07 00:13:24,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--queue-inslast-allhead,184600000,5.190548,28.117811 1120 2023-04-07 00:13:29,3,5 100 72421 -1 3 ,./perfexp--cfa-cfa--stack-insfirst-remelem,325894500,5.111016,15.683039 1121 2023-04-07 00:13:34,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--stack-inslast-allhead,763000000,5.017561,6.576096 1122 2023-04-07 00:13:39,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--queue-inslast-inselem,833000000,5.019453,6.025754 1123 2023-04-07 00:13:44,5,5 10000 809 -1 5 ,./perfexp--lq-tailq--stack-insfirst-remelem,590570000,5.047563,8.546934 1124 2023-04-07 00:13:49,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--queue-insfirst-inselem,436860000,5.034155,11.523497 1125 2023-04-07 00:13:54,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--stack-inslast-remelem,570213000,5.051648,8.859230 1126 2023-04-07 00:13:59,1,5 100000 71 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-allhead,610600000,5.015572,8.214170 1127 2023-04-07 00:14:04,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--queue-insfirst-allhead,1022000000,5.030284,4.922000 1128 2023-04-07 00:14:09,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--stack-inslast-remelem,966000000,5.018343,5.194972 1129 2023-04-07 00:14:14,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--stack-insfirst-remelem,784000000,5.042359,6.431580 1130 2023-04-07 00:14:19,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--stack-inslast-allhead,184600000,5.173540,28.025677 1131 2023-04-07 00:14:25,3,5 100000 71 -1 3 ,./perfexp--upp-upp--stack-inslast-inselem,553800000,5.046826,9.113084 1132 2023-04-07 00:14:30,1,5 10000 809 -1 1 ,./perfexp--upp-upp--stack-inslast-allhead,493490000,5.025143,10.182867 1133 2023-04-07 00:14:35,4,5 100000 71 -1 4 ,./perfexp--lq-list--stack-insfirst-remelem,702900000,5.050739,7.185573 1134 2023-04-07 00:14:40,2,5 1000 9051 -1 2 ,./perfexp--cpp-stlref--stack-insfirst-allhead,162918000,5.172527,31.749267 1135 2023-04-07 00:14:45,4,5 100 72421 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-inselem,159326200,5.130366,32.200391 1136 2023-04-07 00:14:50,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-remelem,830700000,5.005727,6.025914 1137 2023-04-07 00:14:55,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--stack-inslast-allhead,159326200,5.105089,32.041742 1138 2023-04-07 00:15:00,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--stack-insfirst-inselem,581000000,5.027483,8.653155 1139 2023-04-07 00:15:05,5,5 100 72421 -1 5 ,./perfexp--upp-upp--stack-inslast-allhead,159326200,5.079283,31.879772 1140 2023-04-07 00:15:10,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--stack-inslast-remelem,169890000,5.225200,30.756372 1141 2023-04-07 00:15:16,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--stack-inslast-inselem,159326200,5.152960,32.342201 1142 2023-04-07 00:15:21,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--queue-inslast-remelem,777000000,5.023512,6.465266 1143 2023-04-07 00:15:26,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--queue-inslast-inselem,693000000,5.042654,7.276557 1144 2023-04-07 00:15:31,1,5 10000 809 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-allhead,169890000,5.097853,30.006787 1145 2023-04-07 00:15:36,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--queue-inslast-remelem,311410300,5.100699,16.379352 1146 2023-04-07 00:15:41,5,5 100 72421 -1 5 ,./perfexp--cfa-cfa--queue-inslast-inselem,137599900,5.246073,38.125558 1147 2023-04-07 00:15:46,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--stack-inslast-inselem,325836000,5.127345,15.735968 1148 2023-04-07 00:15:52,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--stack-inslast-allhead,325836000,5.027188,15.428584 1149 2023-04-07 00:15:57,3,5 1000000 7 -1 3 ,./perfexp--cpp-stlref--queue-inslast-inselem,224000000,5.015171,22.389156 1150 2023-04-07 00:16:02,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--stack-inslast-inselem,493490000,5.011236,10.154686 1151 2023-04-07 00:16:07,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--queue-insfirst-inselem,546700000,5.018107,9.178904 1152 2023-04-07 00:16:12,1,5 1000000 7 -1 1 ,./perfexp--upp-upp--queue-inslast-allhead,882000000,5.002161,5.671384 1153 2023-04-07 00:16:17,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--stack-inslast-remelem,792820000,5.043780,6.361822 1154 2023-04-07 00:16:22,1,5 100 72421 -1 1 ,./perfexp--upp-upp--stack-inslast-remelem,318652400,5.040033,15.816711 1155 2023-04-07 00:16:27,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--queue-insfirst-inselem,388320000,5.085010,13.094896 1156 2023-04-07 00:16:32,3,5 100 72421 -1 3 ,./perfexp--lq-list--stack-insfirst-remelem,333136600,5.078881,15.245641 1157 2023-04-07 00:16:37,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--queue-inslast-allhead,868000000,5.019333,5.782642 1158 2023-04-07 00:16:42,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--queue-inslast-allhead,177500000,5.028223,28.328017 1159 2023-04-07 00:16:47,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-allhead,631900000,5.013989,7.934782 1160 2023-04-07 00:16:52,5,5 1000000 7 -1 5 ,./perfexp--cpp-stlref--queue-inslast-allhead,224000000,5.103798,22.784813 1161 2023-04-07 00:16:57,3,5 100 72421 -1 3 ,./perfexp--lq-list--stack-insfirst-allhead,166568300,5.053284,30.337609 1162 2023-04-07 00:17:02,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--stack-insfirst-inselem,493490000,5.046497,10.226138 1163 2023-04-07 00:17:07,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--queue-inslast-allhead,334887000,5.070579,15.141164 1164 2023-04-07 00:17:12,3,5 1000 9051 -1 3 ,./perfexp--lq-tailq--queue-inslast-inselem,352989000,5.106015,14.465082 1165 2023-04-07 00:17:18,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--stack-inslast-allhead,672000000,5.053260,7.519732 1166 2023-04-07 00:17:23,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--stack-inslast-inselem,184600000,5.086013,27.551533 1167 2023-04-07 00:17:28,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--queue-inslast-inselem,177500000,5.041333,28.401876 1168 2023-04-07 00:17:33,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--queue-insfirst-remelem,944300000,5.027667,5.324226 1169 2023-04-07 00:17:38,1,5 10000 809 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-remelem,695740000,5.024660,7.222037 1170 2023-04-07 00:17:43,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--queue-insfirst-allhead,130357800,5.060227,38.817984 1171 2023-04-07 00:17:48,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--queue-insfirst-allhead,453040000,5.060348,11.169760 1172 2023-04-07 00:17:53,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--stack-inslast-remelem,1263800000,5.002587,3.958369 1173 2023-04-07 00:17:58,3,5 10000 809 -1 3 ,./perfexp--cpp-stlref--queue-inslast-remelem,169890000,5.032008,29.619212 1174 2023-04-07 00:18:03,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--stack-inslast-inselem,469220000,5.038856,10.738792 1175 2023-04-07 00:18:08,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--stack-inslast-allhead,184600000,5.132353,27.802562 1176 2023-04-07 00:18:13,3,5 10000 809 -1 3 ,./perfexp--lq-tailq--queue-insfirst-inselem,388320000,5.061103,13.033331 1177 2023-04-07 00:18:18,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-inselem,169890000,5.089740,29.959032 1178 2023-04-07 00:18:23,2,5 100 72421 -1 2 ,./perfexp--upp-upp--queue-insfirst-allhead,130357800,5.096965,39.099808 1179 2023-04-07 00:18:29,1,5 1000 9051 -1 1 ,./perfexp--cpp-stlref--queue-inslast-inselem,171969000,5.103011,29.674017 1180 2023-04-07 00:18:34,3,5 1000000 7 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-inselem,658000000,5.036277,7.653916 1181 2023-04-07 00:18:39,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--stack-inslast-inselem,177980000,5.212807,29.288723 1182 2023-04-07 00:18:44,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--stack-inslast-inselem,477310000,5.072814,10.627923 1183 2023-04-07 00:18:49,4,5 100 72421 -1 4 ,./perfexp--lq-tailq--queue-inslast-remelem,311410300,5.096826,16.366915 1184 2023-04-07 00:18:54,4,5 10000 809 -1 4 ,./perfexp--cpp-stlref--stack-inslast-allhead,169890000,5.016611,29.528583 1185 2023-04-07 00:18:59,4,5 100000 71 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-remelem,937200000,5.001450,5.336588 1186 2023-04-07 00:19:04,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--stack-inslast-inselem,588000000,5.027147,8.549570 1187 2023-04-07 00:19:09,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--stack-inslast-inselem,184600000,5.170569,28.009583 1188 2023-04-07 00:19:14,4,5 1000 9051 -1 4 ,./perfexp--cpp-stlref--queue-inslast-allhead,181020000,5.255817,29.034455 1189 2023-04-07 00:19:20,2,5 100000 71 -1 2 ,./perfexp--cfa-cfa--stack-inslast-allhead,603500000,5.004894,8.293114 1190 2023-04-07 00:19:25,4,5 10000 809 -1 4 ,./perfexp--upp-upp--stack-inslast-allhead,493490000,5.060646,10.254810 1191 2023-04-07 00:19:30,4,5 1000000 7 -1 4 ,./perfexp--upp-upp--stack-insfirst-remelem,609000000,5.021341,8.245223 1192 2023-04-07 00:19:35,2,5 1000 9051 -1 2 ,./perfexp--cfa-cfa--queue-inslast-inselem,334887000,5.004467,14.943748 1193 2023-04-07 00:19:40,3,5 10000 809 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-remelem,687650000,5.004454,7.277618 1194 2023-04-07 00:19:45,1,5 100 72421 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-remelem,289684000,5.114885,17.656774 1195 2023-04-07 00:19:50,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--queue-inslast-inselem,485400000,5.081049,10.467756 1196 2023-04-07 00:19:55,5,5 100 72421 -1 5 ,./perfexp--upp-upp--stack-inslast-remelem,318652400,5.038741,15.812657 1197 2023-04-07 00:20:00,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--queue-insfirst-remelem,588315000,5.013924,8.522516 1198 2023-04-07 00:20:05,5,5 1000000 7 -1 5 ,./perfexp--lq-tailq--stack-insfirst-allhead,889000000,5.011883,5.637664 1199 2023-04-07 00:20:10,1,5 10000 809 -1 1 ,./perfexp--upp-upp--stack-inslast-inselem,444950000,5.067489,11.388895 1200 2023-04-07 00:20:15,3,5 100 72421 -1 3 ,./perfexp--cpp-stlref--stack-inslast-allhead,159326200,5.066920,31.802177 1201 2023-04-07 00:20:20,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--queue-inslast-allhead,177500000,5.042851,28.410428 1202 2023-04-07 00:20:25,1,5 100 72421 -1 1 ,./perfexp--upp-upp--queue-inslast-allhead,137599900,5.041518,36.638966 1203 2023-04-07 00:20:30,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--queue-inslast-remelem,534009000,5.035769,9.430120 1204 2023-04-07 00:20:35,5,5 10000 809 -1 5 ,./perfexp--cpp-stlref--queue-inslast-allhead,169890000,5.014708,29.517382 1205 2023-04-07 00:20:40,2,5 10000 809 -1 2 ,./perfexp--cpp-stlref--queue-inslast-remelem,169890000,5.074810,29.871152 1206 2023-04-07 00:20:46,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--queue-inslast-inselem,144842000,5.151741,35.568005 1207 2023-04-07 00:20:51,3,5 10000 809 -1 3 ,./perfexp--upp-upp--queue-inslast-remelem,606750000,5.015496,8.266166 1208 2023-04-07 00:20:56,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--queue-inslast-allhead,334887000,5.048050,15.073891 1209 2023-04-07 00:21:01,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-allhead,665000000,5.000859,7.520089 1210 2023-04-07 00:21:06,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--stack-insfirst-inselem,316785000,5.145817,16.243878 1211 2023-04-07 00:21:11,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--queue-insfirst-inselem,307734000,5.028541,16.340544 1212 2023-04-07 00:21:16,3,5 10000 809 -1 3 ,./perfexp--upp-upp--queue-insfirst-remelem,574390000,5.000948,8.706537 1213 2023-04-07 00:21:21,3,5 1000000 7 -1 3 ,./perfexp--lq-tailq--queue-insfirst-allhead,1022000000,5.024777,4.916612 1214 2023-04-07 00:21:26,5,5 10000 809 -1 5 ,./perfexp--upp-upp--queue-inslast-allhead,493490000,5.064331,10.262277 1215 2023-04-07 00:21:31,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--queue-inslast-inselem,224000000,5.122860,22.869911 1216 2023-04-07 00:21:36,5,5 100000 71 -1 5 ,./perfexp--lq-tailq--queue-inslast-allhead,710000000,5.003407,7.047052 1217 2023-04-07 00:21:41,4,5 1000000 7 -1 4 ,./perfexp--lq-tailq--stack-inslast-allhead,1078000000,5.014066,4.651267 1218 2023-04-07 00:21:46,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--stack-inslast-allhead,224000000,5.121987,22.866013 1219 2023-04-07 00:21:51,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--stack-insfirst-remelem,590570000,5.012351,8.487311 1220 2023-04-07 00:21:56,1,5 100000 71 -1 1 ,./perfexp--cpp-stlref--queue-inslast-remelem,177500000,5.128494,28.892924 1221 2023-04-07 00:22:02,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--queue-insfirst-inselem,184600000,5.024489,27.218250 1222 2023-04-07 00:22:07,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--queue-insfirst-allhead,788100000,5.040492,6.395752 1223 2023-04-07 00:22:12,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--queue-inslast-allhead,461130000,5.072015,10.999100 1224 2023-04-07 00:22:17,5,5 100000 71 -1 5 ,./perfexp--cpp-stlref--queue-inslast-allhead,184600000,5.131083,27.795683 1225 2023-04-07 00:22:22,2,5 100 72421 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-inselem,166568300,5.142531,30.873407 1226 2023-04-07 00:22:27,4,5 100 72421 -1 4 ,./perfexp--lq-list--stack-insfirst-allhead,166568300,5.044477,30.284736 1227 2023-04-07 00:22:32,1,5 100 72421 -1 1 ,./perfexp--upp-upp--stack-inslast-inselem,159326200,5.141698,32.271516 1228 2023-04-07 00:22:37,5,5 1000 9051 -1 5 ,./perfexp--upp-upp--stack-insfirst-allhead,325836000,5.094147,15.634083 1229 2023-04-07 00:22:42,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--stack-inslast-inselem,477310000,5.069685,10.621368 1230 2023-04-07 00:22:47,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--queue-insfirst-inselem,130357800,5.145580,39.472743 1231 2023-04-07 00:22:53,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-inselem,184600000,5.108413,27.672876 1232 2023-04-07 00:22:58,2,5 100 72421 -1 2 ,./perfexp--upp-upp--stack-inslast-remelem,318652400,5.036010,15.804086 1233 2023-04-07 00:23:03,1,5 10000 809 -1 1 ,./perfexp--lq-tailq--queue-insfirst-allhead,461130000,5.085039,11.027344 1234 2023-04-07 00:23:08,2,5 100000 71 -1 2 ,./perfexp--cpp-stlref--queue-insfirst-remelem,184600000,5.172400,28.019502 1235 2023-04-07 00:23:13,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--stack-insfirst-remelem,674500000,5.047846,7.483834 1236 2023-04-07 00:23:18,2,5 1000000 7 -1 2 ,./perfexp--lq-tailq--queue-insfirst-remelem,1309000000,5.005255,3.823724 1237 2023-04-07 00:23:23,4,5 1000000 7 -1 4 ,./perfexp--cfa-cfa--queue-inslast-inselem,658000000,5.016826,7.624356 1238 2023-04-07 00:23:28,4,5 1000 9051 -1 4 ,./perfexp--upp-upp--queue-inslast-remelem,515907000,5.025500,9.741097 1239 2023-04-07 00:23:33,1,5 1000000 7 -1 1 ,./perfexp--cpp-stlref--stack-insfirst-allhead,231000000,5.117156,22.152190 1240 2023-04-07 00:23:38,4,5 10000 809 -1 4 ,./perfexp--lq-tailq--stack-inslast-allhead,509670000,5.046288,9.901089 1241 2023-04-07 00:23:43,3,5 100 72421 -1 3 ,./perfexp--lq-tailq--stack-insfirst-inselem,166568300,5.221492,31.347453 1242 2023-04-07 00:23:49,1,5 100 72421 -1 1 ,./perfexp--lq-tailq--queue-insfirst-remelem,296926100,5.106445,17.197697 1243 2023-04-07 00:23:54,2,5 100 72421 -1 2 ,./perfexp--lq-tailq--stack-insfirst-remelem,333136600,5.079056,15.246166 1244 2023-04-07 00:23:59,4,5 100000 71 -1 4 ,./perfexp--cpp-stlref--queue-inslast-inselem,184600000,5.131130,27.795937 1245 2023-04-07 00:24:04,2,5 100000 71 -1 2 ,./perfexp--lq-tailq--stack-inslast-inselem,880400000,5.012434,5.693360 1246 2023-04-07 00:24:09,2,5 1000 9051 -1 2 ,./perfexp--upp-upp--queue-inslast-inselem,325836000,5.094942,15.636523 1247 2023-04-07 00:24:14,1,5 1000 9051 -1 1 ,./perfexp--lq-tailq--queue-inslast-allhead,352989000,5.061654,14.339410 1248 2023-04-07 00:24:19,5,5 100000 71 -1 5 ,./perfexp--lq-list--stack-insfirst-inselem,731300000,5.012975,6.854882 1249 2023-04-07 00:24:24,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--queue-insfirst-allhead,325836000,5.139636,15.773690 1250 2023-04-07 00:24:30,1,5 1000000 7 -1 1 ,./perfexp--cfa-cfa--stack-insfirst-allhead,665000000,5.024825,7.556128 1251 2023-04-07 00:24:35,1,5 1000 9051 -1 1 ,./perfexp--cfa-cfa--stack-inslast-allhead,334887000,5.006794,14.950697 1252 2023-04-07 00:24:40,3,5 1000 9051 -1 3 ,./perfexp--cfa-cfa--queue-insfirst-allhead,334887000,5.056826,15.100096 1253 2023-04-07 00:24:45,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--queue-inslast-allhead,352989000,5.047526,14.299386 1254 2023-04-07 00:24:50,5,5 1000000 7 -1 5 ,./perfexp--upp-upp--stack-inslast-remelem,903000000,5.002012,5.539327 1255 2023-04-07 00:24:55,1,5 100000 71 -1 1 ,./perfexp--lq-tailq--queue-insfirst-remelem,894600000,5.017897,5.609096 1256 2023-04-07 00:25:00,5,5 100000 71 -1 5 ,./perfexp--cfa-cfa--queue-insfirst-inselem,546700000,5.050560,9.238266 1257 2023-04-07 00:25:05,4,5 1000000 7 -1 4 ,./perfexp--cpp-stlref--stack-insfirst-remelem,231000000,5.084063,22.008931 1258 2023-04-07 00:25:10,2,5 100 72421 -1 2 ,./perfexp--upp-upp--queue-inslast-inselem,137599900,5.086801,36.968057 1259 2023-04-07 00:25:15,2,5 10000 809 -1 2 ,./perfexp--lq-tailq--queue-insfirst-remelem,720010000,5.029074,6.984728 1260 2023-04-07 00:25:20,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--queue-inslast-remelem,534009000,5.024933,9.409828 1261 2023-04-07 00:25:25,4,5 100 72421 -1 4 ,./perfexp--cfa-cfa--stack-insfirst-allhead,159326200,5.104904,32.040581 1262 2023-04-07 00:25:30,3,5 10000 809 -1 3 ,./perfexp--upp-upp--queue-inslast-inselem,444950000,5.013109,11.266679 1263 2023-04-07 00:25:35,3,5 100000 71 -1 3 ,./perfexp--cpp-stlref--stack-inslast-remelem,177500000,5.116110,28.823155 1264 2023-04-07 00:25:41,2,5 10000 809 -1 2 ,./perfexp--cfa-cfa--stack-insfirst-inselem,477310000,5.017041,10.511075 1265 2023-04-07 00:25:46,5,5 100 72421 -1 5 ,./perfexp--lq-tailq--queue-insfirst-allhead,130357800,5.060870,38.822917 1266 2023-04-07 00:25:51,3,5 1000 9051 -1 3 ,./perfexp--upp-upp--stack-insfirst-inselem,307734000,5.017423,16.304416 1267 2023-04-07 00:25:56,2,5 100 72421 -1 2 ,./perfexp--cfa-cfa--queue-inslast-remelem,289684000,5.096670,17.593895 1268 2023-04-07 00:26:01,1,5 1000000 7 -1 1 ,./perfexp--lq-tailq--stack-insfirst-inselem,581000000,5.003206,8.611370 1269 2023-04-07 00:26:06,3,5 100000 71 -1 3 ,./perfexp--cfa-cfa--stack-inslast-remelem,1015300000,5.026273,4.950530 1270 2023-04-07 00:26:11,3,5 100 72421 -1 3 ,./perfexp--upp-upp--stack-insfirst-allhead,159326200,5.149416,32.319957 1271 2023-04-07 00:26:16,4,5 1000 9051 -1 4 ,./perfexp--lq-tailq--stack-inslast-inselem,316785000,5.019917,15.846448 1272 2023-04-07 00:26:21,4,5 10000 809 -1 4 ,./perfexp--cfa-cfa--queue-inslast-remelem,687650000,5.023642,7.305522 1273 2023-04-07 00:26:26,4,5 100000 71 -1 4 ,./perfexp--upp-upp--stack-insfirst-allhead,788100000,5.021043,6.371073 1274 2023-04-07 00:26:31,3,5 100000 71 -1 3 ,./perfexp--lq-tailq--stack-inslast-remelem,1320600000,5.018016,3.799800 1275 2023-04-07 00:26:36,3,5 100000 71 -1 3 ,./perfexp--upp-upp--queue-inslast-remelem,667400000,5.007560,7.503087 -
driver/cfa.cc
ra50fdfb r6e1e2d0 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Feb 14 22:46:38202313 // Update Count : 47 012 // Last Modified On : Mon Apr 10 21:16:00 2023 13 // Update Count : 476 14 14 // 15 15 … … 44 44 static int flags = 0; 45 45 46 // This allocation 'leaks' memory from the program to the execution 47 // environment, as putenv does not manage the storage of the string used 48 // as an environment variable. This leak is necessary to ensure the 49 // underlying C string is allocated long enough. 46 50 if ( putenv( (char *)( *new string( string( __CFA_FLAGPREFIX__ + to_string( flags++ ) + "__=" ) + arg ) ).c_str() ) ) { 47 51 cerr << argv[0] << " error, cannot set environment variable." << endl; … … 198 202 } // if 199 203 } else if ( arg == "-CFA" ) { 200 CFA_flag = true; // strip the-CFA flag204 CFA_flag = true; // strip -CFA flag 201 205 link = false; 202 206 args[nargs++] = "-fsyntax-only"; // stop after stage 2 203 207 } else if ( arg == "-debug" ) { 204 debug = true; // strip thedebug flag208 debug = true; // strip debug flag 205 209 } else if ( arg == "-nodebug" ) { 206 debug = false; // strip thenodebug flag210 debug = false; // strip nodebug flag 207 211 } else if ( arg == "-quiet" ) { 208 quiet = true; // strip thequiet flag212 quiet = true; // strip quiet flag 209 213 } else if ( arg == "-noquiet" ) { 210 quiet = false; // strip the noquiet flag 214 quiet = false; // strip noquiet flag 215 } else if ( arg == "-invariant" ) { 216 Putenv( argv, "-" + arg ); 217 } else if ( arg == "--invariant" ) { 218 Putenv( argv, arg ); 211 219 } else if ( arg == "-no-include-stdhdr" ) { 212 noincstd_flag = true; // strip theno-include-stdhdr flag220 noincstd_flag = true; // strip no-include-stdhdr flag 213 221 } else if ( arg == "-nolib" ) { 214 nolib = true; // strip thenolib flag222 nolib = true; // strip nolib flag 215 223 } else if ( arg == "-help" ) { 216 help = true; // strip thehelp flag224 help = true; // strip help flag 217 225 } else if ( arg == "-nohelp" ) { 218 help = false; // strip thenohelp flag226 help = false; // strip nohelp flag 219 227 } else if ( arg == "-cfalib") { 220 228 compiling_libs = true; … … 274 282 } // if 275 283 } else if ( prefix( arg, "-B" ) ) { 276 bprefix = arg.substr(2); // strip the-B flag284 bprefix = arg.substr(2); // strip -B flag 277 285 } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) { 278 286 args[nargs++] = argv[i]; // pass flag along -
src/AST/Attribute.hpp
ra50fdfb r6e1e2d0 27 27 class Expr; 28 28 29 /// An entry in an attribute list: `__attribute__(( ... ))` 29 30 class Attribute final : public Node { 30 31 public: -
src/AST/Convert.cpp
ra50fdfb r6e1e2d0 559 559 auto stmt = new SuspendStmt(); 560 560 stmt->then = get<CompoundStmt>().accept1( node->then ); 561 switch (node->type) {561 switch (node->kind) { 562 562 case ast::SuspendStmt::None : stmt->type = SuspendStmt::None ; break; 563 563 case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break; … … 1695 1695 GET_ACCEPT_V(attributes, Attribute), 1696 1696 { old->get_funcSpec().val }, 1697 old->type->isVarArgs1697 (old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs 1698 1698 }; 1699 1699 … … 2001 2001 GET_ACCEPT_1(else_, Stmt), 2002 2002 GET_ACCEPT_V(initialization, Stmt), 2003 old->isDoWhile,2003 (old->isDoWhile) ? ast::DoWhile : ast::While, 2004 2004 GET_LABELS_V(old->labels) 2005 2005 ); … … 2143 2143 virtual void visit( const SuspendStmt * old ) override final { 2144 2144 if ( inCache( old ) ) return; 2145 ast::SuspendStmt:: Typetype;2145 ast::SuspendStmt::Kind type; 2146 2146 switch (old->type) { 2147 2147 case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break; -
src/AST/Decl.cpp
ra50fdfb r6e1e2d0 57 57 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 58 58 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs ) 60 60 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), 61 61 type_params(std::move(forall)), assertions(), 62 62 params(std::move(params)), returns(std::move(returns)), stmts( stmts ) { 63 FunctionType * ftype = new FunctionType( static_cast<ArgumentFlag>(isVarArgs));63 FunctionType * ftype = new FunctionType( isVarArgs ); 64 64 for (auto & param : this->params) { 65 65 ftype->params.emplace_back(param->get_type()); … … 81 81 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 82 82 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs ) 84 84 : DeclWithType( location, name, storage, linkage, std::move(attrs), fs ), 85 85 type_params( std::move( forall) ), assertions( std::move( assertions ) ), 86 86 params( std::move(params) ), returns( std::move(returns) ), 87 87 type( nullptr ), stmts( stmts ) { 88 FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs );88 FunctionType * type = new FunctionType( isVarArgs ); 89 89 for ( auto & param : this->params ) { 90 90 type->params.emplace_back( param->get_type() ); -
src/AST/Decl.hpp
ra50fdfb r6e1e2d0 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:44:00 202213 // Update Count : 3 412 // Last Modified On : Wed Apr 5 10:42:00 2023 13 // Update Count : 35 14 14 // 15 15 … … 122 122 }; 123 123 124 /// Function variable arguments flag 125 enum ArgumentFlag { FixedArgs, VariableArgs }; 126 124 127 /// Object declaration `int foo()` 125 128 class FunctionDecl : public DeclWithType { … … 144 147 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 145 148 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 146 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);149 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs ); 147 150 148 151 FunctionDecl( const CodeLocation & location, const std::string & name, … … 150 153 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 151 154 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 152 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);155 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs ); 153 156 154 157 const Type * get_type() const override; … … 313 316 public: 314 317 bool isTyped; // isTyped indicated if the enum has a declaration like: 315 // enum (type_optional) Name {...} 318 // enum (type_optional) Name {...} 316 319 ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum 317 320 enum class EnumHiding { Visible, Hide } hide; … … 371 374 }; 372 375 376 /// Assembly declaration: `asm ... ( "..." : ... )` 373 377 class AsmDecl : public Decl { 374 378 public: -
src/AST/Expr.hpp
ra50fdfb r6e1e2d0 254 254 }; 255 255 256 /// A name qualified by a namespace or type. 256 257 class QualifiedNameExpr final : public Expr { 257 258 public: … … 259 260 std::string name; 260 261 261 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 262 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 262 263 : Expr( loc ), type_decl( d ), name( n ) {} 263 264 … … 621 622 }; 622 623 624 /// A name that refers to a generic dimension parameter. 623 625 class DimensionExpr final : public Expr { 624 626 public: … … 910 912 }; 911 913 912 913 914 } 914 915 -
src/AST/Init.hpp
ra50fdfb r6e1e2d0 117 117 ptr<Init> init; 118 118 119 ConstructorInit( 119 ConstructorInit( 120 120 const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init ) 121 121 : Init( loc, MaybeConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {} -
src/AST/Inspect.cpp
ra50fdfb r6e1e2d0 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Oct 3 11:04:00 202213 // Update Count : 312 // Last Modified On : Fri Apr 14 15:09:00 2023 13 // Update Count : 4 14 14 // 15 15 … … 168 168 } 169 169 170 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) { 171 return obj && obj->name.empty() && obj->bitfieldWidth; 172 } 173 170 174 } // namespace ast -
src/AST/Inspect.hpp
ra50fdfb r6e1e2d0 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Sep 22 13:44:00 202213 // Update Count : 212 // Last Modified On : Fri Apr 14 15:09:00 2023 13 // Update Count : 3 14 14 // 15 15 … … 38 38 const ApplicationExpr * isIntrinsicCallExpr( const Expr * expr ); 39 39 40 /// Returns true if obj's name is the empty string and it has a bitfield width. 41 bool isUnnamedBitfield( const ObjectDecl * obj ); 42 40 43 } -
src/AST/Pass.impl.hpp
ra50fdfb r6e1e2d0 2075 2075 if ( __visit_children() ) { 2076 2076 maybe_accept( node, &TupleType::types ); 2077 maybe_accept( node, &TupleType::members );2078 2077 } 2079 2078 -
src/AST/Print.cpp
ra50fdfb r6e1e2d0 766 766 virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final { 767 767 os << "Suspend Statement"; 768 switch (node-> type) {769 770 771 768 switch (node->kind) { 769 case ast::SuspendStmt::None : os << " with implicit target"; break; 770 case ast::SuspendStmt::Generator: os << " for generator"; break; 771 case ast::SuspendStmt::Coroutine: os << " for coroutine"; break; 772 772 } 773 773 os << endl; -
src/AST/Stmt.hpp
ra50fdfb r6e1e2d0 10 10 // Created On : Wed May 8 13:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 20 14:34:00 202213 // Update Count : 3 612 // Last Modified On : Wed Apr 5 10:34:00 2023 13 // Update Count : 37 14 14 // 15 15 … … 205 205 }; 206 206 207 // A while loop or a do-while loop: 208 enum WhileDoKind { While, DoWhile }; 209 207 210 // While loop: while (...) ... else ... or do ... while (...) else ...; 208 211 class WhileDoStmt final : public Stmt { … … 212 215 ptr<Stmt> else_; 213 216 std::vector<ptr<Stmt>> inits; 214 boolisDoWhile;217 WhileDoKind isDoWhile; 215 218 216 219 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, 217 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )220 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} ) 218 221 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {} 219 222 220 223 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_, 221 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )224 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} ) 222 225 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {} 223 226 … … 364 367 public: 365 368 ptr<CompoundStmt> then; 366 enum Type { None, Coroutine, Generator } type= None;367 368 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )369 : Stmt(loc, std::move(labels)), then(then), type(type) {}369 enum Kind { None, Coroutine, Generator } kind = None; 370 371 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Kind kind, const std::vector<Label> && labels = {} ) 372 : Stmt(loc, std::move(labels)), then(then), kind(kind) {} 370 373 371 374 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } … … 424 427 }; 425 428 429 // Clause in a waitfor statement: waitfor (..., ...) ... 426 430 class WaitForClause final : public WhenClause { 427 431 public: … … 527 531 MUTATE_FRIEND 528 532 }; 533 529 534 } // namespace ast 530 535 -
src/AST/SymbolTable.cpp
ra50fdfb r6e1e2d0 260 260 void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) { 261 261 // default handling of conflicts is to raise an error 262 addId ( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );262 addIdCommon( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 263 263 } 264 264 265 265 void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) { 266 266 // default handling of conflicts is to raise an error 267 addId ( decl, OnConflict::error(), nullptr, deleter );267 addIdCommon( decl, OnConflict::error(), nullptr, deleter ); 268 268 } 269 269 … … 677 677 } 678 678 679 void SymbolTable::addId (680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,681 const Decl * deleter ) {679 void SymbolTable::addIdCommon( 680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, 681 const Expr * baseExpr, const Decl * deleter ) { 682 682 SpecialFunctionKind kind = getSpecialFunctionKind(decl->name); 683 683 if (kind == NUMBER_OF_KINDS) { // not a special decl 684 addId (decl, decl->name, idTable, handleConflicts, baseExpr, deleter);684 addIdToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter); 685 685 } 686 686 else { … … 695 695 assertf(false, "special decl with non-function type"); 696 696 } 697 addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 698 } 699 } 700 701 void SymbolTable::addId( 702 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 703 const Decl * deleter ) { 697 addIdToTable(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 698 } 699 } 700 701 void SymbolTable::addIdToTable( 702 const DeclWithType * decl, const std::string & lookupKey, 703 IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, 704 const Expr * baseExpr, const Decl * deleter ) { 704 705 ++*stats().add_calls; 705 706 const std::string &name = decl->name; … … 778 779 void SymbolTable::addMembers( 779 780 const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) { 780 for ( const Decl *decl : aggr->members ) {781 if ( auto dwt = dynamic_cast< const DeclWithType * >( decl ) ) {782 addId( dwt, handleConflicts, expr );783 if ( dwt->name == "" ) {784 const Type * t = dwt->get_type()->stripReferences();785 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {786 if ( ! dynamic_cast<const StructInstType *>(rty)787 && ! dynamic_cast<const UnionInstType *>(rty) ) continue;788 ResolvExpr::Cost cost = ResolvExpr::Cost::zero;789 ast::ptr<ast::TypeSubstitution> tmp = expr->env;790 expr = mutate_field(expr, &Expr::env, nullptr);791 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );792 base = mutate_field(base, &Expr::env, tmp);793 794 addMembers(795 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts ); 796 }797 }781 for ( const ptr<Decl> & decl : aggr->members ) { 782 auto dwt = decl.as<DeclWithType>(); 783 if ( nullptr == dwt ) continue; 784 addIdCommon( dwt, handleConflicts, expr ); 785 // Inline through unnamed struct/union members. 786 if ( "" != dwt->name ) continue; 787 const Type * t = dwt->get_type()->stripReferences(); 788 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) { 789 if ( ! dynamic_cast<const StructInstType *>(rty) 790 && ! dynamic_cast<const UnionInstType *>(rty) ) continue; 791 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; 792 ast::ptr<ast::TypeSubstitution> tmp = expr->env; 793 expr = mutate_field(expr, &Expr::env, nullptr); 794 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost ); 795 base = mutate_field(base, &Expr::env, tmp); 796 797 addMembers( 798 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts ); 798 799 } 799 800 } -
src/AST/SymbolTable.hpp
ra50fdfb r6e1e2d0 192 192 193 193 /// common code for addId, addDeletedId, etc. 194 void addId (195 const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr,196 const Decl * deleter = nullptr );194 void addIdCommon( 195 const DeclWithType * decl, OnConflict handleConflicts, 196 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr ); 197 197 198 198 /// common code for addId when special decls are placed into separate tables 199 void addId( 200 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts, 199 void addIdToTable( 200 const DeclWithType * decl, const std::string & lookupKey, 201 IdTable::Ptr & idTable, OnConflict handleConflicts, 201 202 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr); 202 203 203 204 /// adds all of the members of the Aggregate (addWith helper) 204 205 void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts ); -
src/AST/Type.cpp
ra50fdfb r6e1e2d0 10 10 // Created On : Mon May 13 15:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:49:00 202213 // Update Count : 612 // Last Modified On : Thu Apr 6 15:59:00 2023 13 // Update Count : 7 14 14 // 15 15 … … 199 199 200 200 TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q ) 201 : Type( q ), types( std::move(ts) ), members() { 202 // This constructor is awkward. `TupleType` needs to contain objects so that members can be 203 // named, but members without initializer nodes end up getting constructors, which breaks 204 // things. This happens because the object decls have to be visited so that their types are 205 // kept in sync with the types listed here. Ultimately, the types listed here should perhaps 206 // be eliminated and replaced with a list-view over members. The temporary solution is to 207 // make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not 208 // constructed. Potential better solutions include: 209 // a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`, 210 // similar to the aggregate types. 211 // b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced 212 // by `genInit`, rather than the current boolean flag. 213 members.reserve( types.size() ); 214 for ( const Type * ty : types ) { 215 members.emplace_back( new ObjectDecl{ 216 CodeLocation(), "", ty, new ListInit( CodeLocation(), {}, {}, NoConstruct ), 217 Storage::Classes{}, Linkage::Cforall } ); 218 } 219 } 201 : Type( q ), types( std::move(ts) ) {} 220 202 221 203 bool isUnboundType(const Type * type) { -
src/AST/Type.hpp
ra50fdfb r6e1e2d0 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:47:00 202213 // Update Count : 812 // Last Modified On : Thu Apr 6 15:58:00 2023 13 // Update Count : 9 14 14 // 15 15 … … 265 265 }; 266 266 267 /// Function variable arguments flag268 enum ArgumentFlag { FixedArgs, VariableArgs };269 270 267 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 271 268 class FunctionType final : public Type { … … 460 457 public: 461 458 std::vector<ptr<Type>> types; 462 std::vector<ptr<Decl>> members;463 459 464 460 TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} ); -
src/Common/CodeLocationTools.cpp
ra50fdfb r6e1e2d0 210 210 211 211 struct LeafKindVisitor : public ast::Visitor { 212 LeafKind kind;212 LeafKind result; 213 213 214 214 #define VISIT(node_type, return_type) \ 215 215 const ast::return_type * visit( const ast::node_type * ) final { \ 216 kind= LeafKind::node_type; \216 result = LeafKind::node_type; \ 217 217 return nullptr; \ 218 218 } … … 224 224 225 225 LeafKind get_leaf_kind( ast::Node const * node ) { 226 LeafKindVisitor visitor; 227 node->accept( visitor ); 228 return visitor.kind; 226 return ast::Pass<LeafKindVisitor>::read( node ); 229 227 } 230 228 -
src/Common/Iterate.hpp
ra50fdfb r6e1e2d0 20 20 #include <iterator> 21 21 22 // it's nice to actually be able to increment iterators by an arbitrary amount22 // Returns an iterator that is it advanced n times. 23 23 template< class InputIt, class Distance > 24 24 InputIt operator+( InputIt it, Distance n ) { … … 50 50 51 51 // ----------------------------------------------------------------------------- 52 // Helper struct and function to support 53 // for ( val_and_index : enumerate( container ) ) {} 54 // which iterates through the container and tracks the index as well. 55 52 56 template< typename T > 53 57 struct enumerate_t { … … 109 113 110 114 // ----------------------------------------------------------------------------- 115 // Helper function to transform one iterable container into another. 116 111 117 template< typename OutType, typename Range, typename Functor > 112 118 OutType map_range( const Range& range, Functor&& functor ) { … … 206 212 // Helper struct and function to support 207 213 // for ( val : lazy_map( container1, f ) ) {} 208 // syntax to have a for each that iterates a container, mapping each element by applying f 214 // syntax to have a for each that iterates a container, 215 // mapping each element by applying f. 216 209 217 template< typename T, typename Func > 210 218 struct lambda_iterate_t { -
src/CompilationState.cc
ra50fdfb r6e1e2d0 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Henry Xue12 // Last Modified On : Tue Jul 20 04:27:35 202113 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 19:12:50 2023 13 // Update Count : 6 14 14 // 15 15 … … 27 27 expraltp = false, 28 28 genericsp = false, 29 invariant = false, 29 30 libcfap = false, 30 31 nopreludep = false, -
src/CompilationState.h
ra50fdfb r6e1e2d0 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Henry Xue12 // Last Modified On : Tue Jul 20 04:27:35 202113 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 19:12:53 2023 13 // Update Count : 6 14 14 // 15 15 … … 26 26 expraltp, 27 27 genericsp, 28 invariant, 28 29 libcfap, 29 30 nopreludep, -
src/Concurrency/KeywordsNew.cpp
ra50fdfb r6e1e2d0 779 779 780 780 const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) { 781 switch ( stmt-> type) {781 switch ( stmt->kind ) { 782 782 case ast::SuspendStmt::None: 783 783 // Use the context to determain the implicit target. -
src/InitTweak/FixInitNew.cpp
ra50fdfb r6e1e2d0 14 14 #include <utility> // for pair 15 15 16 #include "AST/DeclReplacer.hpp" 17 #include "AST/Expr.hpp" 16 18 #include "AST/Inspect.hpp" // for getFunction, getPointerBase, g... 19 #include "AST/Node.hpp" 20 #include "AST/Pass.hpp" 21 #include "AST/Print.hpp" 22 #include "AST/SymbolTable.hpp" 23 #include "AST/Type.hpp" 17 24 #include "CodeGen/GenType.h" // for genPrettyType 18 25 #include "CodeGen/OperatorTable.h" 19 #include "Common/CodeLocationTools.hpp"20 26 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 21 27 #include "Common/SemanticError.h" // for SemanticError … … 28 34 #include "ResolvExpr/Unify.h" // for typesCompatible 29 35 #include "SymTab/Autogen.h" // for genImplicitCall 36 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 30 37 #include "SymTab/Indexer.h" // for Indexer 31 38 #include "SymTab/Mangler.h" // for Mangler … … 45 52 #include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy 46 53 47 #include "AST/Expr.hpp"48 #include "AST/Node.hpp"49 #include "AST/Pass.hpp"50 #include "AST/Print.hpp"51 #include "AST/SymbolTable.hpp"52 #include "AST/Type.hpp"53 #include "AST/DeclReplacer.hpp"54 55 54 extern bool ctordtorp; // print all debug 56 55 extern bool ctorp; // print ctor debug … … 63 62 namespace InitTweak { 64 63 namespace { 64 65 // Shallow copy the pointer list for return. 66 std::vector<ast::ptr<ast::TypeDecl>> getGenericParams( const ast::Type * t ) { 67 if ( auto inst = dynamic_cast<const ast::StructInstType *>( t ) ) { 68 return inst->base->params; 69 } 70 if ( auto inst = dynamic_cast<const ast::UnionInstType *>( t ) ) { 71 return inst->base->params; 72 } 73 return {}; 74 } 75 76 /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &). 77 ast::FunctionDecl * genDefaultFunc( 78 const CodeLocation loc, 79 const std::string fname, 80 const ast::Type * paramType, 81 bool maybePolymorphic = true) { 82 std::vector<ast::ptr<ast::TypeDecl>> typeParams; 83 if ( maybePolymorphic ) typeParams = getGenericParams( paramType ); 84 auto dstParam = new ast::ObjectDecl( loc, 85 "_dst", 86 new ast::ReferenceType( paramType ), 87 nullptr, 88 {}, 89 ast::Linkage::Cforall 90 ); 91 return new ast::FunctionDecl( loc, 92 fname, 93 std::move(typeParams), 94 {dstParam}, 95 {}, 96 new ast::CompoundStmt(loc), 97 {}, 98 ast::Linkage::Cforall 99 ); 100 } 101 65 102 struct SelfAssignChecker { 66 103 void previsit( const ast::ApplicationExpr * appExpr ); … … 121 158 void previsit( const ast::FunctionDecl * ) { visit_children = false; } 122 159 123 160 protected: 124 161 ObjectSet curVars; 125 162 }; … … 202 239 203 240 SemanticErrorException errors; 204 241 private: 205 242 template< typename... Params > 206 243 void emit( CodeLocation, const Params &... params ); … … 288 325 static UniqueName dtorNamer( "__cleanup_dtor" ); 289 326 std::string name = dtorNamer.newName(); 290 ast::FunctionDecl * dtorFunc = SymTab::genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );327 ast::FunctionDecl * dtorFunc = genDefaultFunc( loc, name, objDecl->type->stripReferences(), false ); 291 328 stmtsToAdd.push_back( new ast::DeclStmt(loc, dtorFunc ) ); 292 329 … … 1080 1117 void InsertDtors::previsit( const ast::BranchStmt * stmt ) { 1081 1118 switch( stmt->kind ) { 1082 1083 1119 case ast::BranchStmt::Continue: 1120 case ast::BranchStmt::Break: 1084 1121 // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should 1085 1122 // always be empty), but it serves as a small sanity check. 1086 1123 case ast::BranchStmt::Goto: 1087 1124 handleGoto( stmt ); 1088 1125 break; 1089 1126 default: 1090 1127 assert( false ); 1091 1128 } // switch … … 1312 1349 // xxx - functions returning ast::ptr seems wrong... 1313 1350 auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } ); 1314 // Fix CodeLocation (at least until resolver is fixed). 1315 auto fix = localFillCodeLocations( untypedExpr->location, res.release() ); 1316 return strict_dynamic_cast<const ast::Expr *>( fix ); 1351 return res.release(); 1317 1352 } 1318 1353 -
src/InitTweak/GenInit.cc
ra50fdfb r6e1e2d0 39 39 #include "ResolvExpr/Resolver.h" 40 40 #include "SymTab/Autogen.h" // for genImplicitCall 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 41 42 #include "SymTab/Mangler.h" // for Mangler 42 43 #include "SynTree/LinkageSpec.h" // for isOverridable, C -
src/Parser/DeclarationNode.cc
ra50fdfb r6e1e2d0 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Apr 4 10:28:00 202313 // Update Count : 139 212 // Last Modified On : Thr Apr 20 11:46:00 2023 13 // Update Count : 1393 14 14 // 15 16 #include "DeclarationNode.h" 15 17 16 18 #include <cassert> // for assert, assertf, strict_dynamic_cast … … 34 36 #include "Common/UniqueName.h" // for UniqueName 35 37 #include "Common/utility.h" // for maybeClone 36 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 38 #include "Parser/ExpressionNode.h" // for ExpressionNode 39 #include "Parser/InitializerNode.h"// for InitializerNode 40 #include "Parser/StatementNode.h" // for StatementNode 37 41 #include "TypeData.h" // for TypeData, TypeData::Aggregate_t 38 42 #include "TypedefTable.h" // for TypedefTable … … 999 1003 } 1000 1004 1001 void buildList( const DeclarationNode * firstNode, 1005 // If a typedef wraps an anonymous declaration, name the inner declaration 1006 // so it has a consistent name across translation units. 1007 static void nameTypedefedDecl( 1008 DeclarationNode * innerDecl, 1009 const DeclarationNode * outerDecl ) { 1010 TypeData * outer = outerDecl->type; 1011 assert( outer ); 1012 // First make sure this is a typedef: 1013 if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) { 1014 return; 1015 } 1016 TypeData * inner = innerDecl->type; 1017 assert( inner ); 1018 // Always clear any CVs associated with the aggregate: 1019 inner->qualifiers.reset(); 1020 // Handle anonymous aggregates: typedef struct { int i; } foo 1021 if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) { 1022 delete inner->aggregate.name; 1023 inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1024 inner->aggregate.anon = false; 1025 assert( outer->base ); 1026 delete outer->base->aggInst.aggregate->aggregate.name; 1027 outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1028 outer->base->aggInst.aggregate->aggregate.anon = false; 1029 outer->base->aggInst.aggregate->qualifiers.reset(); 1030 // Handle anonymous enumeration: typedef enum { A, B, C } foo 1031 } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) { 1032 delete inner->enumeration.name; 1033 inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1034 inner->enumeration.anon = false; 1035 assert( outer->base ); 1036 delete outer->base->aggInst.aggregate->enumeration.name; 1037 outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1038 outer->base->aggInst.aggregate->enumeration.anon = false; 1039 // No qualifiers.reset() here. 1040 } 1041 } 1042 1043 // This code handles a special issue with the attribute transparent_union. 1044 // 1045 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 1046 // 1047 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 1048 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 1049 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 1050 // alias. 1051 static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) { 1052 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) { 1053 // Is the typedef alias a union aggregate? 1054 if ( nullptr == unionDecl ) return; 1055 1056 // If typedef is an alias for a union, then its alias type was hoisted above and remembered. 1057 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) { 1058 auto instType = ast::mutate( unionInstType ); 1059 // Remove all transparent_union attributes from typedef and move to alias union. 1060 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { 1061 assert( *attr ); 1062 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 1063 unionDecl->attributes.emplace_back( attr->release() ); 1064 attr = instType->attributes.erase( attr ); 1065 } else { 1066 attr++; 1067 } 1068 } 1069 typedefDecl->base = instType; 1070 } 1071 } 1072 } 1073 1074 // Get the non-anonymous name of the instance type of the declaration, 1075 // if one exists. 1076 static const std::string * getInstTypeOfName( ast::Decl * decl ) { 1077 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1078 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) { 1079 if ( aggr->name.find("anonymous") == std::string::npos ) { 1080 return &aggr->name; 1081 } 1082 } 1083 } 1084 return nullptr; 1085 } 1086 1087 void buildList( DeclarationNode * firstNode, 1002 1088 std::vector<ast::ptr<ast::Decl>> & outputList ) { 1003 1089 SemanticErrorException errors; 1004 1090 std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList ); 1005 1091 1006 for ( const DeclarationNode * cur = firstNode ; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1092 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1007 1093 try { 1008 bool extracted = false, anon= false;1009 ast:: AggregateDecl * unionDecl = nullptr;1094 bool extracted_named = false; 1095 ast::UnionDecl * unionDecl = nullptr; 1010 1096 1011 1097 if ( DeclarationNode * extr = cur->extractAggregate() ) { 1012 // Handle the case where a SUE declaration is contained within an object or type declaration.1013 1014 1098 assert( cur->type ); 1015 // Replace anonymous SUE name with typedef name to prevent anonymous naming problems across translation units. 1016 if ( cur->type->kind == TypeData::Symbolic && cur->type->symbolic.isTypedef ) { 1017 assert( extr->type ); 1018 // Handle anonymous aggregates: typedef struct { int i; } foo 1019 extr->type->qualifiers.reset(); // clear any CVs associated with the aggregate 1020 if ( extr->type->kind == TypeData::Aggregate && extr->type->aggregate.anon ) { 1021 delete extr->type->aggregate.name; 1022 extr->type->aggregate.name = new string( "__anonymous_" + *cur->name ); 1023 extr->type->aggregate.anon = false; 1024 assert( cur->type->base ); 1025 if ( cur->type->base ) { 1026 delete cur->type->base->aggInst.aggregate->aggregate.name; 1027 cur->type->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *cur->name ); 1028 cur->type->base->aggInst.aggregate->aggregate.anon = false; 1029 cur->type->base->aggInst.aggregate->qualifiers.reset(); 1030 } // if 1031 } // if 1032 // Handle anonymous enumeration: typedef enum { A, B, C } foo 1033 if ( extr->type->kind == TypeData::Enum && extr->type->enumeration.anon ) { 1034 delete extr->type->enumeration.name; 1035 extr->type->enumeration.name = new string( "__anonymous_" + *cur->name ); 1036 extr->type->enumeration.anon = false; 1037 assert( cur->type->base ); 1038 if ( cur->type->base ) { 1039 delete cur->type->base->aggInst.aggregate->enumeration.name; 1040 cur->type->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *cur->name ); 1041 cur->type->base->aggInst.aggregate->enumeration.anon = false; 1042 } // if 1043 } // if 1044 } // if 1045 1046 ast::Decl * decl = extr->build(); 1047 if ( decl ) { 1099 nameTypedefedDecl( extr, cur ); 1100 1101 if ( ast::Decl * decl = extr->build() ) { 1048 1102 // Remember the declaration if it is a union aggregate ? 1049 1103 unionDecl = dynamic_cast<ast::UnionDecl *>( decl ); 1050 1104 1051 decl->location = cur->location;1052 1105 *out++ = decl; 1053 1106 1054 1107 // need to remember the cases where a declaration contains an anonymous aggregate definition 1055 extracted = true;1056 1108 assert( extr->type ); 1057 1109 if ( extr->type->kind == TypeData::Aggregate ) { 1058 1110 // typedef struct { int A } B is the only case? 1059 anon =extr->type->aggregate.anon;1111 extracted_named = !extr->type->aggregate.anon; 1060 1112 } else if ( extr->type->kind == TypeData::Enum ) { 1061 1113 // typedef enum { A } B is the only case? 1062 anon = extr->type->enumeration.anon; 1114 extracted_named = !extr->type->enumeration.anon; 1115 } else { 1116 extracted_named = true; 1063 1117 } 1064 1118 } // if … … 1066 1120 } // if 1067 1121 1068 ast::Decl * decl = cur->build(); 1069 if ( decl ) { 1070 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) { 1071 if ( unionDecl ) { // is the typedef alias a union aggregate ? 1072 // This code handles a special issue with the attribute transparent_union. 1073 // 1074 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 1075 // 1076 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 1077 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 1078 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 1079 // alias. 1080 1081 // If typedef is an alias for a union, then its alias type was hoisted above and remembered. 1082 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) { 1083 auto instType = ast::mutate( unionInstType ); 1084 // Remove all transparent_union attributes from typedef and move to alias union. 1085 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { // forward order 1086 assert( *attr ); 1087 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 1088 unionDecl->attributes.emplace_back( attr->release() ); 1089 attr = instType->attributes.erase( attr ); 1090 } else { 1091 attr++; 1092 } // if 1093 } // for 1094 typedefDecl->base = instType; 1095 } // if 1096 } // if 1122 if ( ast::Decl * decl = cur->build() ) { 1123 moveUnionAttribute( decl, unionDecl ); 1124 1125 if ( "" == decl->name && !cur->get_inLine() ) { 1126 // Don't include anonymous declaration for named aggregates, 1127 // but do include them for anonymous aggregates, e.g.: 1128 // struct S { 1129 // struct T { int x; }; // no anonymous member 1130 // struct { int y; }; // anonymous member 1131 // struct T; // anonymous member 1132 // }; 1133 if ( extracted_named ) { 1134 continue; 1135 } 1136 1137 if ( auto name = getInstTypeOfName( decl ) ) { 1138 // Temporary: warn about anonymous member declarations of named types, since 1139 // this conflicts with the syntax for the forward declaration of an anonymous type. 1140 SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() ); 1141 } 1097 1142 } // if 1098 1099 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.: 1100 // struct S { 1101 // struct T { int x; }; // no anonymous member 1102 // struct { int y; }; // anonymous member 1103 // struct T; // anonymous member 1104 // }; 1105 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) { 1106 if ( decl->name == "" ) { 1107 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1108 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) { 1109 if ( aggr->name.find("anonymous") == std::string::npos ) { 1110 if ( ! cur->get_inLine() ) { 1111 // temporary: warn about anonymous member declarations of named types, since 1112 // this conflicts with the syntax for the forward declaration of an anonymous type 1113 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() ); 1114 } // if 1115 } // if 1116 } // if 1117 } // if 1118 } // if 1119 decl->location = cur->location; 1120 *out++ = decl; 1121 } // if 1143 *out++ = decl; 1122 1144 } // if 1123 } catch ( SemanticErrorException & e ) {1145 } catch ( SemanticErrorException & e ) { 1124 1146 errors.append( e ); 1125 1147 } // try … … 1132 1154 1133 1155 // currently only builds assertions, function parameters, and return values 1134 void buildList( constDeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {1156 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) { 1135 1157 SemanticErrorException errors; 1136 1158 std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList ); 1137 1159 1138 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1160 for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) { 1139 1161 try { 1140 1162 ast::Decl * decl = cur->build(); 1141 assert ( decl);1163 assertf( decl, "buildList: build for ast::DeclWithType." ); 1142 1164 if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1143 1165 dwt->location = cur->location; … … 1168 1190 ); 1169 1191 *out++ = obj; 1192 } else { 1193 assertf( false, "buildList: Could not convert to ast::DeclWithType." ); 1170 1194 } // if 1171 } catch ( SemanticErrorException & e ) {1195 } catch ( SemanticErrorException & e ) { 1172 1196 errors.append( e ); 1173 1197 } // try … … 1183 1207 SemanticErrorException errors; 1184 1208 std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList ); 1185 const DeclarationNode * cur = firstNode; 1186 1187 while ( cur ) { 1209 1210 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1188 1211 try { 1189 1212 * out++ = cur->buildType(); 1190 } catch ( SemanticErrorException & e ) {1213 } catch ( SemanticErrorException & e ) { 1191 1214 errors.append( e ); 1192 1215 } // try 1193 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 1194 } // while 1216 } // for 1195 1217 1196 1218 if ( ! errors.isEmpty() ) { -
src/Parser/ExpressionNode.cc
ra50fdfb r6e1e2d0 13 13 // Update Count : 1083 14 14 // 15 16 #include "ExpressionNode.h" 15 17 16 18 #include <cassert> // for assert … … 25 27 #include "Common/SemanticError.h" // for SemanticError 26 28 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 27 #include "ParseNode.h" // for ExpressionNode, maybeMoveBuildType 29 #include "DeclarationNode.h" // for DeclarationNode 30 #include "InitializerNode.h" // for InitializerNode 28 31 #include "parserutility.h" // for notZeroExpr 29 32 … … 699 702 } // build_binary_val 700 703 701 ast::Expr * build_binary_ptr( const CodeLocation & location,702 OperKinds op,703 ExpressionNode * expr_node1,704 ExpressionNode * expr_node2 ) {705 return build_binary_val( location, op, expr_node1, expr_node2 );706 } // build_binary_ptr707 708 704 ast::Expr * build_cond( const CodeLocation & location, 709 705 ExpressionNode * expr_node1, -
src/Parser/InitializerNode.cc
ra50fdfb r6e1e2d0 14 14 // 15 15 16 #include "InitializerNode.h" 17 16 18 #include <iostream> // for operator<<, ostream, basic_ostream 17 19 #include <list> // for list 18 20 #include <string> // for operator<<, string 19 20 using namespace std;21 21 22 22 #include "AST/Expr.hpp" // for Expr … … 24 24 #include "Common/SemanticError.h" // for SemanticError 25 25 #include "Common/utility.h" // for maybeBuild 26 #include "ParseNode.h" // for InitializerNode, ExpressionNode 26 #include "ExpressionNode.h" // for ExpressionNode 27 #include "DeclarationNode.h" // for buildList 28 29 using namespace std; 27 30 28 31 static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) { -
src/Parser/ParseNode.h
ra50fdfb r6e1e2d0 38 38 class DeclarationWithType; 39 39 class Initializer; 40 class InitializerNode; 40 41 class ExpressionNode; 41 42 struct StatementNode; … … 80 81 }; // ParseNode 81 82 82 //##############################################################################83 84 class InitializerNode : public ParseNode {85 public:86 InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );87 InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );88 InitializerNode( bool isDelete );89 ~InitializerNode();90 virtual InitializerNode * clone() const { assert( false ); return nullptr; }91 92 ExpressionNode * get_expression() const { return expr; }93 94 InitializerNode * set_designators( ExpressionNode * des ) { designator = des; return this; }95 ExpressionNode * get_designators() const { return designator; }96 97 InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }98 bool get_maybeConstructed() const { return maybeConstructed; }99 100 bool get_isDelete() const { return isDelete; }101 102 InitializerNode * next_init() const { return kids; }103 104 void print( std::ostream & os, int indent = 0 ) const;105 void printOneLine( std::ostream & ) const;106 107 virtual ast::Init * build() const;108 private:109 ExpressionNode * expr;110 bool aggregate;111 ExpressionNode * designator; // may be list112 InitializerNode * kids;113 bool maybeConstructed;114 bool isDelete;115 }; // InitializerNode116 117 //##############################################################################118 119 class ExpressionNode final : public ParseNode {120 public:121 ExpressionNode( ast::Expr * expr = nullptr ) : expr( expr ) {}122 virtual ~ExpressionNode() {}123 virtual ExpressionNode * clone() const override {124 if ( nullptr == expr ) return nullptr;125 return static_cast<ExpressionNode*>(126 (new ExpressionNode( ast::shallowCopy( expr.get() ) ))->set_next( maybeCopy( get_next() ) ));127 }128 129 bool get_extension() const { return extension; }130 ExpressionNode * set_extension( bool exten ) { extension = exten; return this; }131 132 virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {133 os << expr.get();134 }135 void printOneLine( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}136 137 template<typename T>138 bool isExpressionType() const { return nullptr != dynamic_cast<T>(expr.get()); }139 140 ast::Expr * build() const {141 ast::Expr * node = const_cast<ExpressionNode *>(this)->expr.release();142 node->set_extension( this->get_extension() );143 node->location = this->location;144 return node;145 }146 147 // Public because of lifetime implications (what lifetime implications?)148 std::unique_ptr<ast::Expr> expr;149 private:150 bool extension = false;151 }; // ExpressionNode152 153 83 // Must harmonize with OperName. 154 84 enum class OperKinds { … … 169 99 }; 170 100 171 // These 4 routines modify the string:172 ast::Expr * build_constantInteger( const CodeLocation &, std::string & );173 ast::Expr * build_constantFloat( const CodeLocation &, std::string & );174 ast::Expr * build_constantChar( const CodeLocation &, std::string & );175 ast::Expr * build_constantStr( const CodeLocation &, std::string & );176 ast::Expr * build_field_name_FLOATING_FRACTIONconstant( const CodeLocation &, const std::string & str );177 ast::Expr * build_field_name_FLOATING_DECIMALconstant( const CodeLocation &, const std::string & str );178 ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation &, const std::string & str );179 ast::Expr * build_field_name_fraction_constants( const CodeLocation &, ast::Expr * fieldName, ExpressionNode * fracts );180 181 ast::NameExpr * build_varref( const CodeLocation &, const std::string * name );182 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation &, const DeclarationNode * decl_node, const ast::NameExpr * name );183 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation &, const ast::EnumDecl * decl, const ast::NameExpr * name );184 ast::DimensionExpr * build_dimensionref( const CodeLocation &, const std::string * name );185 186 ast::Expr * build_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node );187 ast::Expr * build_keyword_cast( const CodeLocation &, ast::AggregateDecl::Aggregate target, ExpressionNode * expr_node );188 ast::Expr * build_virtual_cast( const CodeLocation &, DeclarationNode * decl_node, ExpressionNode * expr_node );189 ast::Expr * build_fieldSel( const CodeLocation &, ExpressionNode * expr_node, ast::Expr * member );190 ast::Expr * build_pfieldSel( const CodeLocation &, ExpressionNode * expr_node, ast::Expr * member );191 ast::Expr * build_offsetOf( const CodeLocation &, DeclarationNode * decl_node, ast::NameExpr * member );192 ast::Expr * build_and( const CodeLocation &, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );193 ast::Expr * build_and_or( const CodeLocation &, ExpressionNode * expr_node1, ExpressionNode * expr_node2, ast::LogicalFlag flag );194 ast::Expr * build_unary_val( const CodeLocation &, OperKinds op, ExpressionNode * expr_node );195 ast::Expr * build_binary_val( const CodeLocation &, OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );196 ast::Expr * build_binary_ptr( const CodeLocation &, OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );197 ast::Expr * build_cond( const CodeLocation &, ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 );198 ast::Expr * build_tuple( const CodeLocation &, ExpressionNode * expr_node = nullptr );199 ast::Expr * build_func( const CodeLocation &, ExpressionNode * function, ExpressionNode * expr_node );200 ast::Expr * build_compoundLiteral( const CodeLocation &, DeclarationNode * decl_node, InitializerNode * kids );201 202 //##############################################################################203 204 struct TypeData;205 206 struct DeclarationNode : public ParseNode {207 // These enumerations must harmonize with their names in DeclarationNode.cc.208 enum BasicType {209 Void, Bool, Char, Int, Int128,210 Float, Double, LongDouble, uuFloat80, uuFloat128,211 uFloat16, uFloat32, uFloat32x, uFloat64, uFloat64x, uFloat128, uFloat128x,212 NoBasicType213 };214 static const char * basicTypeNames[];215 enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message216 static const char * complexTypeNames[];217 enum Signedness { Signed, Unsigned, NoSignedness };218 static const char * signednessNames[];219 enum Length { Short, Long, LongLong, NoLength };220 static const char * lengthNames[];221 enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };222 static const char * builtinTypeNames[];223 224 static DeclarationNode * newStorageClass( ast::Storage::Classes );225 static DeclarationNode * newFuncSpecifier( ast::Function::Specs );226 static DeclarationNode * newTypeQualifier( ast::CV::Qualifiers );227 static DeclarationNode * newBasicType( BasicType );228 static DeclarationNode * newComplexType( ComplexType );229 static DeclarationNode * newSignedNess( Signedness );230 static DeclarationNode * newLength( Length );231 static DeclarationNode * newBuiltinType( BuiltinType );232 static DeclarationNode * newForall( DeclarationNode * );233 static DeclarationNode * newFromTypedef( const std::string * );234 static DeclarationNode * newFromGlobalScope();235 static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );236 static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );237 static DeclarationNode * newAggregate( ast::AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );238 static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr, EnumHiding hiding = EnumHiding::Visible );239 static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );240 static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );241 static DeclarationNode * newEnumInLine( const std::string name );242 static DeclarationNode * newName( const std::string * );243 static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );244 static DeclarationNode * newTypeParam( ast::TypeDecl::Kind, const std::string * );245 static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );246 static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );247 static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );248 static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );249 static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );250 static DeclarationNode * newVarArray( DeclarationNode * qualifiers );251 static DeclarationNode * newBitfield( ExpressionNode * size );252 static DeclarationNode * newTuple( DeclarationNode * members );253 static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );254 static DeclarationNode * newVtableType( DeclarationNode * expr );255 static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes256 static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement257 static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement258 static DeclarationNode * newStaticAssert( ExpressionNode * condition, ast::Expr * message );259 260 DeclarationNode();261 ~DeclarationNode();262 DeclarationNode * clone() const override;263 264 DeclarationNode * addQualifiers( DeclarationNode * );265 void checkQualifiers( const TypeData *, const TypeData * );266 void checkSpecifiers( DeclarationNode * );267 DeclarationNode * copySpecifiers( DeclarationNode * );268 DeclarationNode * addType( DeclarationNode * );269 DeclarationNode * addTypedef();270 DeclarationNode * addEnumBase( DeclarationNode * );271 DeclarationNode * addAssertions( DeclarationNode * );272 DeclarationNode * addName( std::string * );273 DeclarationNode * addAsmName( DeclarationNode * );274 DeclarationNode * addBitfield( ExpressionNode * size );275 DeclarationNode * addVarArgs();276 DeclarationNode * addFunctionBody( StatementNode * body, ExpressionNode * with = nullptr );277 DeclarationNode * addOldDeclList( DeclarationNode * list );278 DeclarationNode * setBase( TypeData * newType );279 DeclarationNode * copyAttribute( DeclarationNode * attr );280 DeclarationNode * addPointer( DeclarationNode * qualifiers );281 DeclarationNode * addArray( DeclarationNode * array );282 DeclarationNode * addNewPointer( DeclarationNode * pointer );283 DeclarationNode * addNewArray( DeclarationNode * array );284 DeclarationNode * addParamList( DeclarationNode * list );285 DeclarationNode * addIdList( DeclarationNode * list ); // old-style functions286 DeclarationNode * addInitializer( InitializerNode * init );287 DeclarationNode * addTypeInitializer( DeclarationNode * init );288 289 DeclarationNode * cloneType( std::string * newName );290 DeclarationNode * cloneBaseType( DeclarationNode * newdecl );291 292 DeclarationNode * appendList( DeclarationNode * node ) {293 return (DeclarationNode *)set_last( node );294 }295 296 virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;297 virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;298 299 ast::Decl * build() const;300 ast::Type * buildType() const;301 302 ast::Linkage::Spec get_linkage() const { return linkage; }303 DeclarationNode * extractAggregate() const;304 bool has_enumeratorValue() const { return (bool)enumeratorValue; }305 ExpressionNode * consume_enumeratorValue() const { return const_cast<DeclarationNode *>(this)->enumeratorValue.release(); }306 307 bool get_extension() const { return extension; }308 DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }309 310 bool get_inLine() const { return inLine; }311 DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }312 313 DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }314 315 struct Variable_t {316 // const std::string * name;317 ast::TypeDecl::Kind tyClass;318 DeclarationNode * assertions;319 DeclarationNode * initializer;320 };321 Variable_t variable;322 323 struct StaticAssert_t {324 ExpressionNode * condition;325 ast::Expr * message;326 };327 StaticAssert_t assert;328 329 BuiltinType builtin = NoBuiltinType;330 331 TypeData * type = nullptr;332 333 bool inLine = false;334 bool enumInLine = false;335 ast::Function::Specs funcSpecs;336 ast::Storage::Classes storageClasses;337 338 ExpressionNode * bitfieldWidth = nullptr;339 std::unique_ptr<ExpressionNode> enumeratorValue;340 bool hasEllipsis = false;341 ast::Linkage::Spec linkage;342 ast::Expr * asmName = nullptr;343 std::vector<ast::ptr<ast::Attribute>> attributes;344 InitializerNode * initializer = nullptr;345 bool extension = false;346 std::string error;347 StatementNode * asmStmt = nullptr;348 StatementNode * directiveStmt = nullptr;349 350 static UniqueName anonymous;351 }; // DeclarationNode352 353 ast::Type * buildType( TypeData * type );354 355 static inline ast::Type * maybeMoveBuildType( const DeclarationNode * orig ) {356 ast::Type * ret = orig ? orig->buildType() : nullptr;357 delete orig;358 return ret;359 }360 361 //##############################################################################362 363 struct StatementNode final : public ParseNode {364 StatementNode() :365 stmt( nullptr ), clause( nullptr ) {}366 StatementNode( ast::Stmt * stmt ) :367 stmt( stmt ), clause( nullptr ) {}368 StatementNode( ast::StmtClause * clause ) :369 stmt( nullptr ), clause( clause ) {}370 StatementNode( DeclarationNode * decl );371 virtual ~StatementNode() {}372 373 virtual StatementNode * clone() const final { assert( false ); return nullptr; }374 ast::Stmt * build() const { return const_cast<StatementNode *>(this)->stmt.release(); }375 376 virtual StatementNode * add_label(377 const CodeLocation & location,378 const std::string * name,379 DeclarationNode * attr = nullptr ) {380 stmt->labels.emplace_back( location,381 *name,382 attr ? std::move( attr->attributes )383 : std::vector<ast::ptr<ast::Attribute>>{} );384 delete attr;385 delete name;386 return this;387 }388 389 virtual StatementNode * append_last_case( StatementNode * );390 391 virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {392 os << stmt.get() << std::endl;393 }394 395 std::unique_ptr<ast::Stmt> stmt;396 std::unique_ptr<ast::StmtClause> clause;397 }; // StatementNode398 399 ast::Stmt * build_expr( CodeLocation const &, ExpressionNode * ctl );400 401 struct CondCtl {402 CondCtl( DeclarationNode * decl, ExpressionNode * condition ) :403 init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}404 405 StatementNode * init;406 ExpressionNode * condition;407 };408 409 struct ForCtrl {410 ForCtrl( StatementNode * stmt, ExpressionNode * condition, ExpressionNode * change ) :411 init( stmt ), condition( condition ), change( change ) {}412 413 StatementNode * init;414 ExpressionNode * condition;415 ExpressionNode * change;416 };417 418 ast::Stmt * build_if( const CodeLocation &, CondCtl * ctl, StatementNode * then, StatementNode * else_ );419 ast::Stmt * build_switch( const CodeLocation &, bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );420 ast::CaseClause * build_case( ExpressionNode * ctl );421 ast::CaseClause * build_default( const CodeLocation & );422 ast::Stmt * build_while( const CodeLocation &, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );423 ast::Stmt * build_do_while( const CodeLocation &, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );424 ast::Stmt * build_for( const CodeLocation &, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );425 ast::Stmt * build_branch( const CodeLocation &, ast::BranchStmt::Kind kind );426 ast::Stmt * build_branch( const CodeLocation &, std::string * identifier, ast::BranchStmt::Kind kind );427 ast::Stmt * build_computedgoto( ExpressionNode * ctl );428 ast::Stmt * build_return( const CodeLocation &, ExpressionNode * ctl );429 ast::Stmt * build_throw( const CodeLocation &, ExpressionNode * ctl );430 ast::Stmt * build_resume( const CodeLocation &, ExpressionNode * ctl );431 ast::Stmt * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );432 ast::Stmt * build_try( const CodeLocation &, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );433 ast::CatchClause * build_catch( const CodeLocation &, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );434 ast::FinallyClause * build_finally( const CodeLocation &, StatementNode * stmt );435 ast::Stmt * build_compound( const CodeLocation &, StatementNode * first );436 StatementNode * maybe_build_compound( const CodeLocation &, StatementNode * first );437 ast::Stmt * build_asm( const CodeLocation &, bool voltile, ast::Expr * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );438 ast::Stmt * build_directive( const CodeLocation &, std::string * directive );439 ast::SuspendStmt * build_suspend( const CodeLocation &, StatementNode *, ast::SuspendStmt::Type );440 ast::WaitForStmt * build_waitfor( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt );441 ast::WaitForStmt * build_waitfor_else( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt );442 ast::WaitForStmt * build_waitfor_timeout( const CodeLocation &, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );443 ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation &, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt );444 ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation &, ExpressionNode * when, StatementNode * stmt );445 ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation &, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );446 ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation &, ast::WaitUntilStmt::ClauseNode * root );447 ast::Stmt * build_with( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );448 ast::Stmt * build_mutex( const CodeLocation &, ExpressionNode * exprs, StatementNode * stmt );449 450 //##############################################################################451 452 template<typename AstType, typename NodeType,453 template<typename, typename...> class Container, typename... Args>454 void buildList( const NodeType * firstNode,455 Container<ast::ptr<AstType>, Args...> & output ) {456 SemanticErrorException errors;457 std::back_insert_iterator<Container<ast::ptr<AstType>, Args...>> out( output );458 const NodeType * cur = firstNode;459 460 while ( cur ) {461 try {462 if ( auto result = dynamic_cast<AstType *>( maybeBuild( cur ) ) ) {463 *out++ = result;464 } else {465 assertf(false, __PRETTY_FUNCTION__ );466 SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );467 } // if468 } catch( SemanticErrorException & e ) {469 errors.append( e );470 } // try471 const ParseNode * temp = cur->get_next();472 // Should not return nullptr, then it is non-homogeneous:473 cur = dynamic_cast<const NodeType *>( temp );474 if ( !cur && temp ) {475 SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );476 } // if477 } // while478 if ( ! errors.isEmpty() ) {479 throw errors;480 } // if481 }482 483 // in DeclarationNode.cc484 void buildList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::Decl>> & outputList );485 void buildList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList );486 void buildTypeList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::Type>> & outputList );487 488 template<typename AstType, typename NodeType,489 template<typename, typename...> class Container, typename... Args>490 void buildMoveList( const NodeType * firstNode,491 Container<ast::ptr<AstType>, Args...> & output ) {492 buildList<AstType, NodeType, Container, Args...>( firstNode, output );493 delete firstNode;494 }495 496 // in ParseNode.cc497 101 std::ostream & operator<<( std::ostream & out, const ParseNode * node ); 498 102 -
src/Parser/RunParser.cpp
ra50fdfb r6e1e2d0 20 20 #include "CodeTools/TrackLoc.h" // for fillLocations 21 21 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 22 #include "Parser/ ParseNode.h"// for DeclarationNode, buildList22 #include "Parser/DeclarationNode.h" // for DeclarationNode, buildList 23 23 #include "Parser/TypedefTable.h" // for TypedefTable 24 24 -
src/Parser/StatementNode.cc
ra50fdfb r6e1e2d0 11 11 // Created On : Sat May 16 14:59:41 2015 12 12 // Last Modified By : Andrew Beach 13 // Last Modified On : Tue Apr 4 11:40:00 202314 // Update Count : 42 713 // Last Modified On : Tue Apr 11 10:16:00 2023 14 // Update Count : 428 15 15 // 16 17 #include "StatementNode.h" 16 18 17 19 #include <cassert> // for assert, strict_dynamic_cast, assertf … … 23 25 #include "Common/SemanticError.h" // for SemanticError 24 26 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild 25 #include "ParseNode.h" // for StatementNode, ExpressionNode, bui... 27 #include "DeclarationNode.h" // for DeclarationNode 28 #include "ExpressionNode.h" // for ExpressionNode 26 29 #include "parserutility.h" // for notZeroExpr 27 30 … … 29 32 30 33 using namespace std; 34 35 // Some helpers for cases that really want a single node but check for lists. 36 static const ast::Stmt * buildMoveSingle( StatementNode * node ) { 37 std::vector<ast::ptr<ast::Stmt>> list; 38 buildMoveList( node, list ); 39 assertf( list.size() == 1, "CFA Internal Error: Extra/Missing Nodes" ); 40 return list.front().release(); 41 } 42 43 static const ast::Stmt * buildMoveOptional( StatementNode * node ) { 44 std::vector<ast::ptr<ast::Stmt>> list; 45 buildMoveList( node, list ); 46 assertf( list.size() <= 1, "CFA Internal Error: Extra Nodes" ); 47 return list.empty() ? nullptr : list.front().release(); 48 } 31 49 32 50 StatementNode::StatementNode( DeclarationNode * decl ) { … … 53 71 } // StatementNode::StatementNode 54 72 55 StatementNode * StatementNode::append_last_case( StatementNode * stmt ) { 56 StatementNode * prev = this; 73 StatementNode * StatementNode::add_label( 74 const CodeLocation & location, 75 const std::string * name, 76 DeclarationNode * attr ) { 77 stmt->labels.emplace_back( location, 78 *name, 79 attr ? std::move( attr->attributes ) 80 : std::vector<ast::ptr<ast::Attribute>>{} ); 81 delete attr; 82 delete name; 83 return this; 84 } 85 86 ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) { 87 ClauseNode * prev = this; 57 88 // find end of list and maintain previous pointer 58 for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) { 59 StatementNode * node = strict_dynamic_cast< StatementNode * >(curr); 60 assert( nullptr == node->stmt.get() ); 89 for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) { 90 ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr); 61 91 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) ); 62 92 prev = curr; 63 93 } // for 94 ClauseNode * node = dynamic_cast< ClauseNode * >(prev); 64 95 // convert from StatementNode list to Statement list 65 StatementNode * node = dynamic_cast< StatementNode * >(prev);66 96 std::vector<ast::ptr<ast::Stmt>> stmts; 67 97 buildMoveList( stmt, stmts ); … … 73 103 stmts.clear(); 74 104 return this; 75 } // StatementNode::append_last_case105 } // ClauseNode::append_last_case 76 106 77 107 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) { … … 97 127 for ( ast::ptr<ast::Stmt> & stmt : inits ) { 98 128 // build the && of all of the declared variables compared against 0 99 //auto declStmt = strict_dynamic_cast<ast::DeclStmt *>( stmt );100 129 auto declStmt = stmt.strict_as<ast::DeclStmt>(); 101 //ast::DeclWithType * dwt = strict_dynamic_cast<ast::DeclWithType *>( declStmt->decl );102 130 auto dwt = declStmt->decl.strict_as<ast::DeclWithType>(); 103 131 ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) ); … … 113 141 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 114 142 115 std::vector<ast::ptr<ast::Stmt>> aststmt; 116 buildMoveList( then, aststmt ); 117 assert( aststmt.size() == 1 ); 118 ast::Stmt const * astthen = aststmt.front().release(); 119 120 ast::Stmt const * astelse = nullptr; 121 if ( else_ ) { 122 std::vector<ast::ptr<ast::Stmt>> aststmt; 123 buildMoveList( else_, aststmt ); 124 assert( aststmt.size() == 1 ); 125 astelse = aststmt.front().release(); 126 } // if 143 ast::Stmt const * astthen = buildMoveSingle( then ); 144 ast::Stmt const * astelse = buildMoveOptional( else_ ); 127 145 128 146 return new ast::IfStmt( location, astcond, astthen, astelse, … … 131 149 } // build_if 132 150 133 // Temporary work around. Split StmtClause off from StatementNode. 134 template<typename clause_t> 135 static void buildMoveClauseList( StatementNode * firstNode, 136 std::vector<ast::ptr<clause_t>> & output ) { 137 SemanticErrorException errors; 138 std::back_insert_iterator<std::vector<ast::ptr<clause_t>>> 139 out( output ); 140 StatementNode * cur = firstNode; 141 142 while ( cur ) { 143 try { 144 auto clause = cur->clause.release(); 145 if ( auto result = dynamic_cast<clause_t *>( clause ) ) { 146 *out++ = result; 147 } else { 148 assertf(false, __PRETTY_FUNCTION__ ); 149 SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." ); 150 } // if 151 } catch( SemanticErrorException & e ) { 152 errors.append( e ); 153 } // try 154 ParseNode * temp = cur->get_next(); 155 // Should not return nullptr, then it is non-homogeneous: 156 cur = dynamic_cast<StatementNode *>( temp ); 157 if ( !cur && temp ) { 158 SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." ); 159 } // if 160 } // while 161 if ( ! errors.isEmpty() ) { 162 throw errors; 163 } // if 164 // Usually in the wrapper. 165 delete firstNode; 166 } 167 168 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) { 151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) { 169 152 std::vector<ast::ptr<ast::CaseClause>> aststmt; 170 buildMove ClauseList( stmt, aststmt );153 buildMoveList( stmt, aststmt ); 171 154 // If it is not a switch it is a choose statement. 172 155 if ( ! isSwitch ) { … … 190 173 } // build_switch 191 174 192 ast::CaseClause * build_case( ExpressionNode * ctl ) {175 ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) { 193 176 // stmt starts empty and then added to 194 177 auto expr = maybeMoveBuild( ctl ); 195 return new ast::CaseClause( expr->location, expr, {} );178 return new ast::CaseClause( location, expr, {} ); 196 179 } // build_case 197 180 … … 205 188 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 206 189 207 std::vector<ast::ptr<ast::Stmt>> aststmt; // loop body, compound created if empty208 buildMoveList( stmt, aststmt );209 assert( aststmt.size() == 1 );210 211 std::vector<ast::ptr<ast::Stmt>> astelse; // else clause, maybe empty212 buildMoveList( else_, astelse );213 assert( astelse.size() <= 1 );214 215 190 return new ast::WhileDoStmt( location, 216 191 astcond, 217 aststmt.front(),218 astelse.empty() ? nullptr : astelse.front().release(),192 buildMoveSingle( stmt ), 193 buildMoveOptional( else_ ), 219 194 std::move( astinit ), 220 false195 ast::While 221 196 ); 222 197 } // build_while 223 198 224 199 ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) { 225 std::vector<ast::ptr<ast::Stmt>> aststmt; // loop body, compound created if empty226 buildMoveList( stmt, aststmt );227 assert( aststmt.size() == 1 ); // compound created if empty228 229 std::vector<ast::ptr<ast::Stmt>> astelse; // else clause, maybe empty230 buildMoveList( else_, astelse );231 assert( astelse.size() <= 1 );232 233 200 // do-while cannot have declarations in the contitional, so init is always empty 234 201 return new ast::WhileDoStmt( location, 235 202 notZeroExpr( maybeMoveBuild( ctl ) ), 236 aststmt.front(),237 astelse.empty() ? nullptr : astelse.front().release(),203 buildMoveSingle( stmt ), 204 buildMoveOptional( else_ ), 238 205 {}, 239 true206 ast::DoWhile 240 207 ); 241 208 } // build_do_while … … 251 218 astincr = maybeMoveBuild( forctl->change ); 252 219 delete forctl; 253 254 std::vector<ast::ptr<ast::Stmt>> aststmt; // loop body, compound created if empty255 buildMoveList( stmt, aststmt );256 assert( aststmt.size() == 1 );257 258 std::vector<ast::ptr<ast::Stmt>> astelse; // else clause, maybe empty259 buildMoveList( else_, astelse );260 assert( astelse.size() <= 1 );261 220 262 221 return new ast::ForStmt( location, … … 264 223 astcond, 265 224 astincr, 266 aststmt.front(),267 astelse.empty() ? nullptr : astelse.front().release()225 buildMoveSingle( stmt ), 226 buildMoveOptional( else_ ) 268 227 ); 269 228 } // build_for … … 326 285 } // build_resume_at 327 286 328 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) { 329 288 std::vector<ast::ptr<ast::CatchClause>> aststmt; 330 buildMove ClauseList( catch_, aststmt );289 buildMoveList( catch_, aststmt ); 331 290 ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) ); 332 291 ast::FinallyClause * finallyBlock = nullptr; … … 342 301 343 302 ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) { 344 std::vector<ast::ptr<ast::Stmt>> aststmt;345 buildMoveList( body, aststmt );346 assert( aststmt.size() == 1 );347 303 return new ast::CatchClause( location, 348 304 kind, 349 305 maybeMoveBuild( decl ), 350 306 maybeMoveBuild( cond ), 351 aststmt.front().release()307 buildMoveSingle( body ) 352 308 ); 353 309 } // build_catch 354 310 355 311 ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) { 356 std::vector<ast::ptr<ast::Stmt>> aststmt;357 buildMoveList( stmt, aststmt );358 assert( aststmt.size() == 1 );359 312 return new ast::FinallyClause( location, 360 aststmt.front().strict_as<ast::CompoundStmt>() 313 strict_dynamic_cast<const ast::CompoundStmt *>( 314 buildMoveSingle( stmt ) 315 ) 361 316 ); 362 317 } // build_finally 363 318 364 ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Type type ) { 365 std::vector<ast::ptr<ast::Stmt>> stmts; 366 buildMoveList( then, stmts ); 367 ast::CompoundStmt const * then2 = nullptr; 368 if(!stmts.empty()) { 369 assert( stmts.size() == 1 ); 370 then2 = stmts.front().strict_as<ast::CompoundStmt>(); 371 } 372 auto node = new ast::SuspendStmt( location, then2, ast::SuspendStmt::None ); 373 node->type = type; 374 return node; 319 ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) { 320 return new ast::SuspendStmt( location, 321 strict_dynamic_cast<const ast::CompoundStmt *, nullptr>( 322 buildMoveOptional( then ) 323 ), 324 kind 325 ); 375 326 } // build_suspend 376 327 … … 525 476 526 477 // Question 527 ast::Stmt * build_asm( const CodeLocation & location, bool voltile, ast::Expr* instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {478 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) { 528 479 std::vector<ast::ptr<ast::Expr>> out, in; 529 480 std::vector<ast::ptr<ast::ConstantExpr>> clob; … … 533 484 buildMoveList( clobber, clob ); 534 485 return new ast::AsmStmt( location, 535 voltile,536 instruction,486 is_volatile, 487 maybeMoveBuild( instruction ), 537 488 std::move( out ), 538 489 std::move( in ), -
src/Parser/TypeData.cc
ra50fdfb r6e1e2d0 24 24 #include "Common/SemanticError.h" // for SemanticError 25 25 #include "Common/utility.h" // for splice, spliceBegin 26 #include "Parser/ parserutility.h" // for maybeCopy, maybeBuild, maybeMoveB...27 #include "Parser/ ParseNode.h" // for DeclarationNode, ExpressionNode26 #include "Parser/ExpressionNode.h" // for ExpressionNode 27 #include "Parser/StatementNode.h" // for StatementNode 28 28 29 29 class Attribute; … … 1397 1397 std::move( attributes ), 1398 1398 funcSpec, 1399 isVarArgs1399 (isVarArgs) ? ast::VariableArgs : ast::FixedArgs 1400 1400 ); 1401 1401 buildList( td->function.withExprs, decl->withExprs ); -
src/Parser/TypeData.h
ra50fdfb r6e1e2d0 16 16 #pragma once 17 17 18 #include <iosfwd> 19 #include <list> 20 #include <string> 18 #include <iosfwd> // for ostream 19 #include <list> // for list 20 #include <string> // for string 21 21 22 #include "AST/Type.hpp" 23 #include " ParseNode.h" // for DeclarationNode, DeclarationNode::Ag...22 #include "AST/Type.hpp" // for Type 23 #include "DeclarationNode.h" // for DeclarationNode 24 24 25 25 struct TypeData { -
src/Parser/TypedefTable.cc
ra50fdfb r6e1e2d0 16 16 17 17 #include "TypedefTable.h" 18 #include <cassert> // for assert 19 #include <iostream> 18 19 #include <cassert> // for assert 20 #include <string> // for string 21 #include <iostream> // for iostream 22 23 #include "ExpressionNode.h" // for LabelNode 24 #include "ParserTypes.h" // for Token 25 #include "StatementNode.h" // for CondCtl, ForCtrl 26 // This (generated) header must come late as it is missing includes. 27 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname 28 20 29 using namespace std; 21 30 22 31 #if 0 23 32 #define debugPrint( code ) code 33 34 static const char *kindName( int kind ) { 35 switch ( kind ) { 36 case IDENTIFIER: return "identifier"; 37 case TYPEDIMname: return "typedim"; 38 case TYPEDEFname: return "typedef"; 39 case TYPEGENname: return "typegen"; 40 default: 41 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl; 42 abort(); 43 } // switch 44 } // kindName 24 45 #else 25 46 #define debugPrint( code ) 26 47 #endif 27 28 using namespace std; // string, iostream29 30 debugPrint(31 static const char *kindName( int kind ) {32 switch ( kind ) {33 case IDENTIFIER: return "identifier";34 case TYPEDIMname: return "typedim";35 case TYPEDEFname: return "typedef";36 case TYPEGENname: return "typegen";37 default:38 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;39 abort();40 } // switch41 } // kindName42 );43 48 44 49 TypedefTable::~TypedefTable() { … … 78 83 typedefTable.addToEnclosingScope( name, kind, "MTD" ); 79 84 } // if 85 } // TypedefTable::makeTypedef 86 87 void TypedefTable::makeTypedef( const string & name ) { 88 return makeTypedef( name, TYPEDEFname ); 80 89 } // TypedefTable::makeTypedef 81 90 -
src/Parser/TypedefTable.h
ra50fdfb r6e1e2d0 19 19 20 20 #include "Common/ScopedMap.h" // for ScopedMap 21 #include "ParserTypes.h"22 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname23 21 24 22 class TypedefTable { 25 23 struct Note { size_t level; bool forall; }; 26 24 typedef ScopedMap< std::string, int, Note > KindTable; 27 KindTable kindTable; 25 KindTable kindTable; 28 26 unsigned int level = 0; 29 27 public: … … 33 31 bool existsCurr( const std::string & identifier ) const; 34 32 int isKind( const std::string & identifier ) const; 35 void makeTypedef( const std::string & name, int kind = TYPEDEFname ); 33 void makeTypedef( const std::string & name, int kind ); 34 void makeTypedef( const std::string & name ); 36 35 void addToScope( const std::string & identifier, int kind, const char * ); 37 36 void addToEnclosingScope( const std::string & identifier, int kind, const char * ); -
src/Parser/lex.ll
ra50fdfb r6e1e2d0 44 44 45 45 #include "config.h" // configure info 46 #include "DeclarationNode.h" // for DeclarationNode 47 #include "ExpressionNode.h" // for LabelNode 48 #include "InitializerNode.h" // for InitializerNode 46 49 #include "ParseNode.h" 50 #include "ParserTypes.h" // for Token 51 #include "StatementNode.h" // for CondCtl, ForCtrl 47 52 #include "TypedefTable.h" 53 // This (generated) header must come late as it is missing includes. 54 #include "parser.hh" // generated info 48 55 49 56 string * build_postfix_name( string * name ); -
src/Parser/module.mk
ra50fdfb r6e1e2d0 21 21 SRC += \ 22 22 Parser/DeclarationNode.cc \ 23 Parser/DeclarationNode.h \ 23 24 Parser/ExpressionNode.cc \ 25 Parser/ExpressionNode.h \ 24 26 Parser/InitializerNode.cc \ 27 Parser/InitializerNode.h \ 25 28 Parser/lex.ll \ 26 29 Parser/ParseNode.cc \ … … 33 36 Parser/RunParser.hpp \ 34 37 Parser/StatementNode.cc \ 38 Parser/StatementNode.h \ 35 39 Parser/TypeData.cc \ 36 40 Parser/TypeData.h \ -
src/Parser/parser.yy
ra50fdfb r6e1e2d0 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Apr 4 14:02:00202313 // Update Count : 63 2911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 26 16:45:37 2023 13 // Update Count : 6330 14 14 // 15 15 … … 48 48 using namespace std; 49 49 50 #include "SynTree/Declaration.h" 51 #include "ParseNode.h" 50 #include "SynTree/Type.h" // for Type 51 #include "DeclarationNode.h" // for DeclarationNode, ... 52 #include "ExpressionNode.h" // for ExpressionNode, ... 53 #include "InitializerNode.h" // for InitializerNode, ... 54 #include "ParserTypes.h" 55 #include "StatementNode.h" // for build_... 52 56 #include "TypedefTable.h" 53 57 #include "TypeData.h" 54 #include "SynTree/LinkageSpec.h"55 58 #include "Common/SemanticError.h" // error_str 56 59 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... … … 297 300 %union { 298 301 Token tok; 299 ParseNode * pn; 300 ExpressionNode * en; 302 ExpressionNode * expr; 301 303 DeclarationNode * decl; 302 304 ast::AggregateDecl::Aggregate aggKey; 303 305 ast::TypeDecl::Kind tclass; 304 StatementNode * sn; 306 StatementNode * stmt; 307 ClauseNode * clause; 305 308 ast::WaitForStmt * wfs; 306 ast::WaitUntilStmt::ClauseNode * wuscn; 307 ast::Expr * constant; 309 ast::WaitUntilStmt::ClauseNode * wucn; 308 310 CondCtl * ifctl; 309 ForCtrl * fctl; 310 OperKinds compop; 311 LabelNode * label; 312 InitializerNode * in; 313 OperKinds op; 311 ForCtrl * forctl; 312 LabelNode * labels; 313 InitializerNode * init; 314 OperKinds oper; 314 315 std::string * str; 315 bool flag;316 EnumHiding hide;317 ast::ExceptionKind catch_kind;316 bool is_volatile; 317 EnumHiding enum_hiding; 318 ast::ExceptionKind except_kind; 318 319 ast::GenericExpr * genexpr; 319 320 } … … 381 382 %type<tok> identifier identifier_at identifier_or_type_name attr_name 382 383 %type<tok> quasi_keyword 383 %type< constant> string_literal384 %type<expr> string_literal 384 385 %type<str> string_literal_list 385 386 386 %type< hide> hide_opt visible_hide_opt387 %type<enum_hiding> hide_opt visible_hide_opt 387 388 388 389 // expressions 389 %type<e n> constant390 %type<e n> tuple tuple_expression_list391 %type<op > ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator392 %type<e n> primary_expression postfix_expression unary_expression393 %type<e n> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression394 %type<e n> shift_expression relational_expression equality_expression395 %type<e n> AND_expression exclusive_OR_expression inclusive_OR_expression396 %type<e n> logical_AND_expression logical_OR_expression397 %type<e n> conditional_expression constant_expression assignment_expression assignment_expression_opt398 %type<e n> comma_expression comma_expression_opt399 %type<e n> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt390 %type<expr> constant 391 %type<expr> tuple tuple_expression_list 392 %type<oper> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator 393 %type<expr> primary_expression postfix_expression unary_expression 394 %type<expr> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression 395 %type<expr> shift_expression relational_expression equality_expression 396 %type<expr> AND_expression exclusive_OR_expression inclusive_OR_expression 397 %type<expr> logical_AND_expression logical_OR_expression 398 %type<expr> conditional_expression constant_expression assignment_expression assignment_expression_opt 399 %type<expr> comma_expression comma_expression_opt 400 %type<expr> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt 400 401 %type<ifctl> conditional_declaration 401 %type<f ctl> for_control_expression for_control_expression_list402 %type< compop> upupeq updown updowneq downupdowneq403 %type<e n> subrange402 %type<forctl> for_control_expression for_control_expression_list 403 %type<oper> upupeq updown updowneq downupdowneq 404 %type<expr> subrange 404 405 %type<decl> asm_name_opt 405 %type<e n> asm_operands_opt asm_operands_list asm_operand406 %type<label > label_list407 %type<e n> asm_clobbers_list_opt408 %type< flag> asm_volatile_opt409 %type<e n> handler_predicate_opt406 %type<expr> asm_operands_opt asm_operands_list asm_operand 407 %type<labels> label_list 408 %type<expr> asm_clobbers_list_opt 409 %type<is_volatile> asm_volatile_opt 410 %type<expr> handler_predicate_opt 410 411 %type<genexpr> generic_association generic_assoc_list 411 412 412 413 // statements 413 %type<sn> statement labeled_statement compound_statement 414 %type<sn> statement_decl statement_decl_list statement_list_nodecl 415 %type<sn> selection_statement if_statement 416 %type<sn> switch_clause_list_opt switch_clause_list 417 %type<en> case_value 418 %type<sn> case_clause case_value_list case_label case_label_list 419 %type<sn> iteration_statement jump_statement 420 %type<sn> expression_statement asm_statement 421 %type<sn> with_statement 422 %type<en> with_clause_opt 423 %type<sn> exception_statement handler_clause finally_clause 424 %type<catch_kind> handler_key 425 %type<sn> mutex_statement 426 %type<en> when_clause when_clause_opt waitfor waituntil timeout 427 %type<sn> waitfor_statement waituntil_statement 414 %type<stmt> statement labeled_statement compound_statement 415 %type<stmt> statement_decl statement_decl_list statement_list_nodecl 416 %type<stmt> selection_statement if_statement 417 %type<clause> switch_clause_list_opt switch_clause_list 418 %type<expr> case_value 419 %type<clause> case_clause case_value_list case_label case_label_list 420 %type<stmt> iteration_statement jump_statement 421 %type<stmt> expression_statement asm_statement 422 %type<stmt> with_statement 423 %type<expr> with_clause_opt 424 %type<stmt> exception_statement 425 %type<clause> handler_clause finally_clause 426 %type<except_kind> handler_key 427 %type<stmt> mutex_statement 428 %type<expr> when_clause when_clause_opt waitfor waituntil timeout 429 %type<stmt> waitfor_statement waituntil_statement 428 430 %type<wfs> wor_waitfor_clause 429 %type<wu scn> waituntil_clause wand_waituntil_clause wor_waituntil_clause431 %type<wucn> waituntil_clause wand_waituntil_clause wor_waituntil_clause 430 432 431 433 // declarations … … 439 441 %type<decl> assertion assertion_list assertion_list_opt 440 442 441 %type<e n> bit_subrange_size_opt bit_subrange_size443 %type<expr> bit_subrange_size_opt bit_subrange_size 442 444 443 445 %type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type … … 452 454 453 455 %type<decl> enumerator_list enum_type enum_type_nobody 454 %type<in > enumerator_value_opt456 %type<init> enumerator_value_opt 455 457 456 458 %type<decl> external_definition external_definition_list external_definition_list_opt … … 459 461 460 462 %type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract 461 %type<e n> field field_name_list field_name fraction_constants_opt463 %type<expr> field field_name_list field_name fraction_constants_opt 462 464 463 465 %type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr … … 508 510 %type<decl> type_parameter type_parameter_list type_initializer_opt 509 511 510 %type<e n> type_parameters_opt type_list array_type_list512 %type<expr> type_parameters_opt type_list array_type_list 511 513 512 514 %type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list … … 519 521 520 522 // initializers 521 %type<in > initializer initializer_list_opt initializer_opt523 %type<init> initializer initializer_list_opt initializer_opt 522 524 523 525 // designators 524 %type<e n> designator designator_list designation526 %type<expr> designator designator_list designation 525 527 526 528 … … 644 646 645 647 string_literal: 646 string_literal_list { $$ = build_constantStr( yylloc, *$1); }648 string_literal_list { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 ) ); } 647 649 ; 648 650 … … 739 741 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 740 742 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"] 741 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }743 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 742 744 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 743 745 { … … 757 759 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 758 760 | string_literal '`' identifier // CFA, postfix call 759 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), new ExpressionNode( $1 )) ); }761 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 760 762 | postfix_expression '.' identifier 761 763 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } … … 857 859 | constant 858 860 | string_literal 859 { $$ = new ExpressionNode( $1 ); }861 { $$ = $1; } 860 862 | EXTENSION cast_expression // GCC 861 863 { $$ = $2->set_extension( true ); } … … 1260 1262 1261 1263 case_value_list: // CFA 1262 case_value { $$ = new StatementNode( build_case($1 ) ); }1264 case_value { $$ = new ClauseNode( build_case( yylloc, $1 ) ); } 1263 1265 // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5" 1264 | case_value_list ',' case_value { $$ = (StatementNode *)($1->set_last( new StatementNode( build_case( $3 )) ) ); }1266 | case_value_list ',' case_value { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3 ) ) ); } 1265 1267 ; 1266 1268 … … 1271 1273 | CASE case_value_list error // syntax error 1272 1274 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; } 1273 | DEFAULT ':' { $$ = new StatementNode( build_default( yylloc ) ); }1275 | DEFAULT ':' { $$ = new ClauseNode( build_default( yylloc ) ); } 1274 1276 // A semantic check is required to ensure only one default clause per switch/choose statement. 1275 1277 | DEFAULT error // syntax error … … 1279 1281 case_label_list: // CFA 1280 1282 case_label 1281 | case_label_list case_label { $$ = (StatementNode *)( $1->set_last( $2 )); }1283 | case_label_list case_label { $$ = $1->set_last( $2 ); } 1282 1284 ; 1283 1285 … … 1296 1298 { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); } 1297 1299 | switch_clause_list case_label_list statement_list_nodecl 1298 { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 )) ) ) ); }1300 { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ); } 1299 1301 ; 1300 1302 … … 1679 1681 1680 1682 waituntil: 1681 WAITUNTIL '(' c ast_expression ')'1683 WAITUNTIL '(' comma_expression ')' 1682 1684 { $$ = $3; } 1683 1685 ; … … 1736 1738 handler_clause: 1737 1739 handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1738 { $$ = new StatementNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }1740 { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); } 1739 1741 | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1740 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }1742 { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); } 1741 1743 ; 1742 1744 … … 1755 1757 1756 1758 finally_clause: 1757 FINALLY compound_statement { $$ = new StatementNode( build_finally( yylloc, $2 ) ); }1759 FINALLY compound_statement { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); } 1758 1760 ; 1759 1761 … … 1813 1815 asm_operand: // GCC 1814 1816 string_literal '(' constant_expression ')' 1815 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", $1, maybeMoveBuild( $3 ) ) ); }1817 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 1816 1818 | '[' IDENTIFIER ']' string_literal '(' constant_expression ')' 1817 1819 { 1818 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, $4, maybeMoveBuild( $6 ) ) );1820 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) ); 1819 1821 delete $2.str; 1820 1822 } … … 1825 1827 { $$ = nullptr; } // use default argument 1826 1828 | string_literal 1827 { $$ = new ExpressionNode( $1 ); }1829 { $$ = $1; } 1828 1830 | asm_clobbers_list_opt ',' string_literal 1829 { $$ = (ExpressionNode *)( $1->set_last( new ExpressionNode( $3 ) )); }1831 { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); } 1830 1832 ; 1831 1833 … … 1899 1901 static_assert: 1900 1902 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11 1901 { $$ = DeclarationNode::newStaticAssert( $3, $5); }1903 { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 ) ); } 1902 1904 | STATICASSERT '(' constant_expression ')' ';' // CFA 1903 1905 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); } … … 3329 3331 { 3330 3332 DeclarationNode * name = new DeclarationNode(); 3331 name->asmName = $3;3333 name->asmName = maybeMoveBuild( $3 ); 3332 3334 $$ = name->addQualifiers( $5 ); 3333 3335 } -
src/Parser/parserutility.h
ra50fdfb r6e1e2d0 24 24 25 25 template< typename T > 26 static inline auto maybeBuild( const T *orig ) -> decltype(orig->build()) {26 static inline auto maybeBuild( T * orig ) -> decltype(orig->build()) { 27 27 return (orig) ? orig->build() : nullptr; 28 28 } 29 29 30 30 template< typename T > 31 static inline auto maybeMoveBuild( const T *orig ) -> decltype(orig->build()) {31 static inline auto maybeMoveBuild( T * orig ) -> decltype(orig->build()) { 32 32 auto ret = maybeBuild<T>(orig); 33 33 delete orig; -
src/ResolvExpr/CandidateFinder.cpp
ra50fdfb r6e1e2d0 55 55 namespace ResolvExpr { 56 56 57 /// Unique identifier for matching expression resolutions to their requesting expression 58 UniqueId globalResnSlot = 0; 59 60 namespace { 61 /// First index is which argument, second is which alternative, third is which exploded element 62 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >; 63 64 /// Returns a list of alternatives with the minimum cost in the given list 65 CandidateList findMinCost( const CandidateList & candidates ) { 66 CandidateList out; 67 Cost minCost = Cost::infinity; 68 for ( const CandidateRef & r : candidates ) { 69 if ( r->cost < minCost ) { 70 minCost = r->cost; 71 out.clear(); 72 out.emplace_back( r ); 73 } else if ( r->cost == minCost ) { 74 out.emplace_back( r ); 75 } 76 } 77 return out; 78 } 79 80 /// Computes conversion cost for a given expression to a given type 81 const ast::Expr * computeExpressionConversionCost( 82 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 83 ) { 84 Cost convCost = computeConversionCost( 85 arg->result, paramType, arg->get_lvalue(), symtab, env ); 86 outCost += convCost; 87 88 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 89 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 90 // infer parameters and this does not currently work for the reason stated below 91 Cost tmpCost = convCost; 92 tmpCost.incPoly( -tmpCost.get_polyCost() ); 93 if ( tmpCost != Cost::zero ) { 94 ast::ptr< ast::Type > newType = paramType; 95 env.apply( newType ); 96 return new ast::CastExpr{ arg, newType }; 97 98 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 99 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 100 // once this is fixed it should be possible to resolve the cast. 101 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 102 // but it shouldn't be because this makes the conversion from DT* to DT* since 103 // commontype(zero_t, DT*) is DT*, rather than nothing 104 105 // CandidateFinder finder{ symtab, env }; 106 // finder.find( arg, ResolvMode::withAdjustment() ); 107 // assertf( finder.candidates.size() > 0, 108 // "Somehow castable expression failed to find alternatives." ); 109 // assertf( finder.candidates.size() == 1, 110 // "Somehow got multiple alternatives for known cast expression." ); 111 // return finder.candidates.front()->expr; 112 } 113 114 return arg; 115 } 116 117 /// Computes conversion cost for a given candidate 118 Cost computeApplicationConversionCost( 119 CandidateRef cand, const ast::SymbolTable & symtab 120 ) { 121 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >(); 122 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 123 auto function = pointer->base.strict_as< ast::FunctionType >(); 124 125 Cost convCost = Cost::zero; 126 const auto & params = function->params; 127 auto param = params.begin(); 128 auto & args = appExpr->args; 129 130 for ( unsigned i = 0; i < args.size(); ++i ) { 131 const ast::Type * argType = args[i]->result; 132 PRINT( 133 std::cerr << "arg expression:" << std::endl; 134 ast::print( std::cerr, args[i], 2 ); 135 std::cerr << "--- results are" << std::endl; 136 ast::print( std::cerr, argType, 2 ); 137 ) 138 139 if ( param == params.end() ) { 140 if ( function->isVarArgs ) { 141 convCost.incUnsafe(); 142 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 143 << convCost << std::endl; ; ) 144 // convert reference-typed expressions into value-typed expressions 145 cand->expr = ast::mutate_field_index( 146 appExpr, &ast::ApplicationExpr::args, i, 147 referenceToRvalueConversion( args[i], convCost ) ); 148 continue; 149 } else return Cost::infinity; 150 } 151 152 if ( auto def = args[i].as< ast::DefaultArgExpr >() ) { 153 // Default arguments should be free - don't include conversion cost. 154 // Unwrap them here because they are not relevant to the rest of the system 155 cand->expr = ast::mutate_field_index( 156 appExpr, &ast::ApplicationExpr::args, i, def->expr ); 157 ++param; 158 continue; 159 } 160 161 // mark conversion cost and also specialization cost of param type 162 // const ast::Type * paramType = (*param)->get_type(); 163 cand->expr = ast::mutate_field_index( 164 appExpr, &ast::ApplicationExpr::args, i, 165 computeExpressionConversionCost( 166 args[i], *param, symtab, cand->env, convCost ) ); 167 convCost.decSpec( specCost( *param ) ); 168 ++param; // can't be in for-loop update because of the continue 169 } 170 171 if ( param != params.end() ) return Cost::infinity; 172 173 // specialization cost of return types can't be accounted for directly, it disables 174 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 175 // 176 // forall(otype OS) { 177 // void ?|?(OS&, int); // with newline 178 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 179 // } 180 181 // mark type variable and specialization cost of forall clause 182 convCost.incVar( function->forall.size() ); 183 convCost.decSpec( function->assertions.size() ); 184 185 return convCost; 186 } 187 188 void makeUnifiableVars( 189 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars, 190 ast::AssertionSet & need 191 ) { 192 for ( auto & tyvar : type->forall ) { 193 unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base }; 194 } 195 for ( auto & assn : type->assertions ) { 196 need[ assn ].isUsed = true; 197 } 198 } 199 200 /// Gets a default value from an initializer, nullptr if not present 201 const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) { 202 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) { 203 if ( auto ce = si->value.as< ast::CastExpr >() ) { 204 return ce->arg.as< ast::ConstantExpr >(); 205 } else { 206 return si->value.as< ast::ConstantExpr >(); 207 } 208 } 209 return nullptr; 210 } 211 212 /// State to iteratively build a match of parameter expressions to arguments 213 struct ArgPack { 214 std::size_t parent; ///< Index of parent pack 215 ast::ptr< ast::Expr > expr; ///< The argument stored here 216 Cost cost; ///< The cost of this argument 217 ast::TypeEnvironment env; ///< Environment for this pack 218 ast::AssertionSet need; ///< Assertions outstanding for this pack 219 ast::AssertionSet have; ///< Assertions found for this pack 220 ast::OpenVarSet open; ///< Open variables for this pack 221 unsigned nextArg; ///< Index of next argument in arguments list 222 unsigned tupleStart; ///< Number of tuples that start at this index 223 unsigned nextExpl; ///< Index of next exploded element 224 unsigned explAlt; ///< Index of alternative for nextExpl > 0 225 226 ArgPack() 227 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 228 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 229 230 ArgPack( 231 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 232 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 233 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 234 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 235 236 ArgPack( 237 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 238 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 239 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 240 unsigned nextExpl = 0, unsigned explAlt = 0 ) 241 : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ), 242 have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ), 243 nextExpl( nextExpl ), explAlt( explAlt ) {} 244 245 ArgPack( 246 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 247 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added ) 248 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ), 249 need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), 250 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {} 251 252 /// true if this pack is in the middle of an exploded argument 253 bool hasExpl() const { return nextExpl > 0; } 254 255 /// Gets the list of exploded candidates for this pack 256 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const { 257 return args[ nextArg-1 ][ explAlt ]; 258 } 259 260 /// Ends a tuple expression, consolidating the appropriate args 261 void endTuple( const std::vector< ArgPack > & packs ) { 262 // add all expressions in tuple to list, summing cost 263 std::deque< const ast::Expr * > exprs; 264 const ArgPack * pack = this; 265 if ( expr ) { exprs.emplace_front( expr ); } 266 while ( pack->tupleStart == 0 ) { 267 pack = &packs[pack->parent]; 268 exprs.emplace_front( pack->expr ); 269 cost += pack->cost; 270 } 271 // reset pack to appropriate tuple 272 std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() ); 273 expr = new ast::TupleExpr{ expr->location, std::move( exprv ) }; 274 tupleStart = pack->tupleStart - 1; 275 parent = pack->parent; 276 } 277 }; 278 279 /// Instantiates an argument to match a parameter, returns false if no matching results left 280 bool instantiateArgument( 281 const CodeLocation & location, 282 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 283 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 284 unsigned nTuples = 0 285 ) { 286 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { 287 // paramType is a TupleType -- group args into a TupleExpr 288 ++nTuples; 289 for ( const ast::Type * type : *tupleType ) { 290 // xxx - dropping initializer changes behaviour from previous, but seems correct 291 // ^^^ need to handle the case where a tuple has a default argument 292 if ( ! instantiateArgument( location, 293 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 294 nTuples = 0; 295 } 296 // re-constitute tuples for final generation 297 for ( auto i = genStart; i < results.size(); ++i ) { 298 results[i].endTuple( results ); 299 } 300 return true; 301 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) { 302 // paramType is a ttype, consumes all remaining arguments 303 304 // completed tuples; will be spliced to end of results to finish 305 std::vector< ArgPack > finalResults{}; 306 307 // iterate until all results completed 308 std::size_t genEnd; 309 ++nTuples; 310 do { 311 genEnd = results.size(); 312 313 // add another argument to results 314 for ( std::size_t i = genStart; i < genEnd; ++i ) { 315 unsigned nextArg = results[i].nextArg; 316 317 // use next element of exploded tuple if present 318 if ( results[i].hasExpl() ) { 319 const ExplodedArg & expl = results[i].getExpl( args ); 320 321 unsigned nextExpl = results[i].nextExpl + 1; 322 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 323 324 results.emplace_back( 325 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 326 copy( results[i].need ), copy( results[i].have ), 327 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl, 328 results[i].explAlt ); 329 330 continue; 331 } 332 333 // finish result when out of arguments 334 if ( nextArg >= args.size() ) { 335 ArgPack newResult{ 336 results[i].env, results[i].need, results[i].have, results[i].open }; 337 newResult.nextArg = nextArg; 338 const ast::Type * argType = nullptr; 339 340 if ( nTuples > 0 || ! results[i].expr ) { 341 // first iteration or no expression to clone, 342 // push empty tuple expression 343 newResult.parent = i; 344 newResult.expr = new ast::TupleExpr( location, {} ); 345 argType = newResult.expr->result; 346 } else { 347 // clone result to collect tuple 348 newResult.parent = results[i].parent; 349 newResult.cost = results[i].cost; 350 newResult.tupleStart = results[i].tupleStart; 351 newResult.expr = results[i].expr; 352 argType = newResult.expr->result; 353 354 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 355 // the case where a ttype value is passed directly is special, 356 // e.g. for argument forwarding purposes 357 // xxx - what if passing multiple arguments, last of which is 358 // ttype? 359 // xxx - what would happen if unify was changed so that unifying 360 // tuple 361 // types flattened both before unifying lists? then pass in 362 // TupleType (ttype) below. 363 --newResult.tupleStart; 364 } else { 365 // collapse leftover arguments into tuple 366 newResult.endTuple( results ); 367 argType = newResult.expr->result; 368 } 369 } 370 371 // check unification for ttype before adding to final 372 if ( 373 unify( 374 ttype, argType, newResult.env, newResult.need, newResult.have, 375 newResult.open, symtab ) 376 ) { 377 finalResults.emplace_back( std::move( newResult ) ); 378 } 379 380 continue; 381 } 382 383 // add each possible next argument 384 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 385 const ExplodedArg & expl = args[nextArg][j]; 386 387 // fresh copies of parent parameters for this iteration 388 ast::TypeEnvironment env = results[i].env; 389 ast::OpenVarSet open = results[i].open; 390 391 env.addActual( expl.env, open ); 392 393 // skip empty tuple arguments by (nearly) cloning parent into next gen 394 if ( expl.exprs.empty() ) { 395 results.emplace_back( 396 results[i], std::move( env ), copy( results[i].need ), 397 copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost ); 398 399 continue; 400 } 401 402 // add new result 403 results.emplace_back( 404 i, expl.exprs.front(), std::move( env ), copy( results[i].need ), 405 copy( results[i].have ), std::move( open ), nextArg + 1, nTuples, 406 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 407 } 408 } 409 410 // reset for next round 411 genStart = genEnd; 412 nTuples = 0; 413 } while ( genEnd != results.size() ); 414 415 // splice final results onto results 416 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 417 results.emplace_back( std::move( finalResults[i] ) ); 418 } 419 return ! finalResults.empty(); 420 } 421 422 // iterate each current subresult 423 std::size_t genEnd = results.size(); 424 for ( std::size_t i = genStart; i < genEnd; ++i ) { 425 unsigned nextArg = results[i].nextArg; 426 427 // use remainder of exploded tuple if present 428 if ( results[i].hasExpl() ) { 429 const ExplodedArg & expl = results[i].getExpl( args ); 430 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ]; 431 432 ast::TypeEnvironment env = results[i].env; 433 ast::AssertionSet need = results[i].need, have = results[i].have; 434 ast::OpenVarSet open = results[i].open; 435 436 const ast::Type * argType = expr->result; 437 438 PRINT( 439 std::cerr << "param type is "; 440 ast::print( std::cerr, paramType ); 441 std::cerr << std::endl << "arg type is "; 442 ast::print( std::cerr, argType ); 443 std::cerr << std::endl; 444 ) 445 446 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 447 unsigned nextExpl = results[i].nextExpl + 1; 448 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 449 450 results.emplace_back( 451 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg, 452 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 453 } 454 455 continue; 456 } 457 458 // use default initializers if out of arguments 459 if ( nextArg >= args.size() ) { 460 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) { 461 ast::TypeEnvironment env = results[i].env; 462 ast::AssertionSet need = results[i].need, have = results[i].have; 463 ast::OpenVarSet open = results[i].open; 464 465 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 466 results.emplace_back( 467 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ), 468 std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples ); 469 } 470 } 471 472 continue; 473 } 474 475 // Check each possible next argument 476 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 477 const ExplodedArg & expl = args[nextArg][j]; 478 479 // fresh copies of parent parameters for this iteration 480 ast::TypeEnvironment env = results[i].env; 481 ast::AssertionSet need = results[i].need, have = results[i].have; 482 ast::OpenVarSet open = results[i].open; 483 484 env.addActual( expl.env, open ); 485 486 // skip empty tuple arguments by (nearly) cloning parent into next gen 487 if ( expl.exprs.empty() ) { 488 results.emplace_back( 489 results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ), 490 nextArg + 1, expl.cost ); 491 492 continue; 493 } 494 495 // consider only first exploded arg 496 const ast::Expr * expr = expl.exprs.front(); 497 const ast::Type * argType = expr->result; 498 499 PRINT( 500 std::cerr << "param type is "; 501 ast::print( std::cerr, paramType ); 502 std::cerr << std::endl << "arg type is "; 503 ast::print( std::cerr, argType ); 504 std::cerr << std::endl; 505 ) 506 507 // attempt to unify types 508 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 509 // add new result 510 results.emplace_back( 511 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 512 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 513 } 514 } 515 } 516 517 // reset for next parameter 518 genStart = genEnd; 519 520 return genEnd != results.size(); // were any new results added? 521 } 522 523 /// Generate a cast expression from `arg` to `toType` 524 const ast::Expr * restructureCast( 525 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast 526 ) { 527 if ( 528 arg->result->size() > 1 529 && ! toType->isVoid() 530 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 531 ) { 532 // Argument is a tuple and the target type is neither void nor a reference. Cast each 533 // member of the tuple to its corresponding target type, producing the tuple of those 534 // cast expressions. If there are more components of the tuple than components in the 535 // target type, then excess components do not come out in the result expression (but 536 // UniqueExpr ensures that the side effects will still be produced) 537 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 538 // expressions which may contain side effects require a single unique instance of 539 // the expression 540 arg = new ast::UniqueExpr{ arg->location, arg }; 541 } 542 std::vector< ast::ptr< ast::Expr > > components; 543 for ( unsigned i = 0; i < toType->size(); ++i ) { 544 // cast each component 545 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 546 components.emplace_back( 547 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 548 } 549 return new ast::TupleExpr{ arg->location, std::move( components ) }; 550 } else { 551 // handle normally 552 return new ast::CastExpr{ arg->location, arg, toType, isGenerated }; 553 } 554 } 555 556 /// Gets the name from an untyped member expression (must be NameExpr) 557 const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) { 558 if ( memberExpr->member.as< ast::ConstantExpr >() ) { 559 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " ); 560 } 561 562 return memberExpr->member.strict_as< ast::NameExpr >()->name; 563 } 564 565 /// Actually visits expressions to find their candidate interpretations 566 class Finder final : public ast::WithShortCircuiting { 567 const ResolveContext & context; 568 const ast::SymbolTable & symtab; 569 public: 570 // static size_t traceId; 571 CandidateFinder & selfFinder; 572 CandidateList & candidates; 573 const ast::TypeEnvironment & tenv; 574 ast::ptr< ast::Type > & targetType; 575 576 enum Errors { 577 NotFound, 578 NoMatch, 579 ArgsToFew, 580 ArgsToMany, 581 RetsToFew, 582 RetsToMany, 583 NoReason 584 }; 585 586 struct { 587 Errors code = NotFound; 588 } reason; 589 590 Finder( CandidateFinder & f ) 591 : context( f.context ), symtab( context.symtab ), selfFinder( f ), 592 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {} 593 594 void previsit( const ast::Node * ) { visit_children = false; } 595 596 /// Convenience to add candidate to list 597 template<typename... Args> 598 void addCandidate( Args &&... args ) { 599 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } ); 600 reason.code = NoReason; 601 } 602 603 void postvisit( const ast::ApplicationExpr * applicationExpr ) { 604 addCandidate( applicationExpr, tenv ); 605 } 606 607 /// Set up candidate assertions for inference 608 void inferParameters( CandidateRef & newCand, CandidateList & out ); 609 610 /// Completes a function candidate with arguments located 611 void validateFunctionCandidate( 612 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 613 CandidateList & out ); 614 615 /// Builds a list of candidates for a function, storing them in out 616 void makeFunctionCandidates( 617 const CodeLocation & location, 618 const CandidateRef & func, const ast::FunctionType * funcType, 619 const ExplodedArgs_new & args, CandidateList & out ); 620 621 /// Adds implicit struct-conversions to the alternative list 622 void addAnonConversions( const CandidateRef & cand ); 623 624 /// Adds aggregate member interpretations 625 void addAggMembers( 626 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 627 const Candidate & cand, const Cost & addedCost, const std::string & name 628 ); 629 630 /// Adds tuple member interpretations 631 void addTupleMembers( 632 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 633 const Cost & addedCost, const ast::Expr * member 634 ); 635 636 /// true if expression is an lvalue 637 static bool isLvalue( const ast::Expr * x ) { 638 return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() ); 639 } 640 641 void postvisit( const ast::UntypedExpr * untypedExpr ); 642 void postvisit( const ast::VariableExpr * variableExpr ); 643 void postvisit( const ast::ConstantExpr * constantExpr ); 644 void postvisit( const ast::SizeofExpr * sizeofExpr ); 645 void postvisit( const ast::AlignofExpr * alignofExpr ); 646 void postvisit( const ast::AddressExpr * addressExpr ); 647 void postvisit( const ast::LabelAddressExpr * labelExpr ); 648 void postvisit( const ast::CastExpr * castExpr ); 649 void postvisit( const ast::VirtualCastExpr * castExpr ); 650 void postvisit( const ast::KeywordCastExpr * castExpr ); 651 void postvisit( const ast::UntypedMemberExpr * memberExpr ); 652 void postvisit( const ast::MemberExpr * memberExpr ); 653 void postvisit( const ast::NameExpr * nameExpr ); 654 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ); 655 void postvisit( const ast::OffsetofExpr * offsetofExpr ); 656 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ); 657 void postvisit( const ast::LogicalExpr * logicalExpr ); 658 void postvisit( const ast::ConditionalExpr * conditionalExpr ); 659 void postvisit( const ast::CommaExpr * commaExpr ); 660 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ); 661 void postvisit( const ast::ConstructorExpr * ctorExpr ); 662 void postvisit( const ast::RangeExpr * rangeExpr ); 663 void postvisit( const ast::UntypedTupleExpr * tupleExpr ); 664 void postvisit( const ast::TupleExpr * tupleExpr ); 665 void postvisit( const ast::TupleIndexExpr * tupleExpr ); 666 void postvisit( const ast::TupleAssignExpr * tupleExpr ); 667 void postvisit( const ast::UniqueExpr * unqExpr ); 668 void postvisit( const ast::StmtExpr * stmtExpr ); 669 void postvisit( const ast::UntypedInitExpr * initExpr ); 670 671 void postvisit( const ast::InitExpr * ) { 672 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); 673 } 674 675 void postvisit( const ast::DeletedExpr * ) { 676 assertf( false, "CandidateFinder should never see a DeletedExpr." ); 677 } 678 679 void postvisit( const ast::GenericExpr * ) { 680 assertf( false, "_Generic is not yet supported." ); 681 } 682 }; 683 684 /// Set up candidate assertions for inference 685 void Finder::inferParameters( CandidateRef & newCand, CandidateList & out ) { 686 // Set need bindings for any unbound assertions 687 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 688 for ( auto & assn : newCand->need ) { 689 // skip already-matched assertions 690 if ( assn.second.resnSlot != 0 ) continue; 691 // assign slot for expression if needed 692 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 693 // fix slot to assertion 694 assn.second.resnSlot = crntResnSlot; 695 } 696 // pair slot to expression 697 if ( crntResnSlot != 0 ) { 698 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot ); 699 } 700 701 // add to output list; assertion satisfaction will occur later 702 out.emplace_back( newCand ); 703 } 704 705 /// Completes a function candidate with arguments located 706 void Finder::validateFunctionCandidate( 707 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 708 CandidateList & out 709 ) { 710 ast::ApplicationExpr * appExpr = 711 new ast::ApplicationExpr{ func->expr->location, func->expr }; 712 // sum cost and accumulate arguments 713 std::deque< const ast::Expr * > args; 714 Cost cost = func->cost; 715 const ArgPack * pack = &result; 716 while ( pack->expr ) { 717 args.emplace_front( pack->expr ); 718 cost += pack->cost; 719 pack = &results[pack->parent]; 720 } 721 std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() ); 722 appExpr->args = std::move( vargs ); 723 // build and validate new candidate 724 auto newCand = 725 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 726 PRINT( 727 std::cerr << "instantiate function success: " << appExpr << std::endl; 728 std::cerr << "need assertions:" << std::endl; 729 ast::print( std::cerr, result.need, 2 ); 730 ) 731 inferParameters( newCand, out ); 732 } 733 734 /// Builds a list of candidates for a function, storing them in out 735 void Finder::makeFunctionCandidates( 736 const CodeLocation & location, 737 const CandidateRef & func, const ast::FunctionType * funcType, 738 const ExplodedArgs_new & args, CandidateList & out 739 ) { 740 ast::OpenVarSet funcOpen; 741 ast::AssertionSet funcNeed, funcHave; 742 ast::TypeEnvironment funcEnv{ func->env }; 743 makeUnifiableVars( funcType, funcOpen, funcNeed ); 744 // add all type variables as open variables now so that those not used in the 745 // parameter list are still considered open 746 funcEnv.add( funcType->forall ); 747 748 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) { 749 // attempt to narrow based on expected target type 750 const ast::Type * returnType = funcType->returns.front(); 751 if ( ! unify( 752 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 753 ) { 754 // unification failed, do not pursue this candidate 755 return; 756 } 757 } 758 759 // iteratively build matches, one parameter at a time 760 std::vector< ArgPack > results; 761 results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen ); 762 std::size_t genStart = 0; 763 764 // xxx - how to handle default arg after change to ftype representation? 765 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) { 766 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) { 767 // function may have default args only if directly calling by name 768 // must use types on candidate however, due to RenameVars substitution 769 auto nParams = funcType->params.size(); 770 771 for (size_t i=0; i<nParams; ++i) { 772 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 773 if (!instantiateArgument( location, 774 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 775 } 776 goto endMatch; 777 } 778 } 779 for ( const auto & param : funcType->params ) { 780 // Try adding the arguments corresponding to the current parameter to the existing 781 // matches 782 // no default args for indirect calls 783 if ( ! instantiateArgument( location, 784 param, nullptr, args, results, genStart, symtab ) ) return; 785 } 786 787 endMatch: 788 if ( funcType->isVarArgs ) { 789 // append any unused arguments to vararg pack 790 std::size_t genEnd; 791 do { 792 genEnd = results.size(); 793 794 // iterate results 795 for ( std::size_t i = genStart; i < genEnd; ++i ) { 796 unsigned nextArg = results[i].nextArg; 797 798 // use remainder of exploded tuple if present 799 if ( results[i].hasExpl() ) { 800 const ExplodedArg & expl = results[i].getExpl( args ); 801 802 unsigned nextExpl = results[i].nextExpl + 1; 803 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 804 805 results.emplace_back( 806 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 807 copy( results[i].need ), copy( results[i].have ), 808 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl, 809 results[i].explAlt ); 810 811 continue; 812 } 813 814 // finish result when out of arguments 815 if ( nextArg >= args.size() ) { 816 validateFunctionCandidate( func, results[i], results, out ); 817 818 continue; 819 } 820 821 // add each possible next argument 822 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 823 const ExplodedArg & expl = args[nextArg][j]; 824 825 // fresh copies of parent parameters for this iteration 826 ast::TypeEnvironment env = results[i].env; 827 ast::OpenVarSet open = results[i].open; 828 829 env.addActual( expl.env, open ); 830 831 // skip empty tuple arguments by (nearly) cloning parent into next gen 832 if ( expl.exprs.empty() ) { 833 results.emplace_back( 834 results[i], std::move( env ), copy( results[i].need ), 835 copy( results[i].have ), std::move( open ), nextArg + 1, 836 expl.cost ); 837 838 continue; 839 } 840 841 // add new result 842 results.emplace_back( 843 i, expl.exprs.front(), std::move( env ), copy( results[i].need ), 844 copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost, 845 expl.exprs.size() == 1 ? 0 : 1, j ); 846 } 847 } 848 849 genStart = genEnd; 850 } while( genEnd != results.size() ); 851 } else { 852 // filter out the results that don't use all the arguments 853 for ( std::size_t i = genStart; i < results.size(); ++i ) { 854 ArgPack & result = results[i]; 855 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 856 validateFunctionCandidate( func, result, results, out ); 857 } 858 } 859 } 860 } 861 862 /// Adds implicit struct-conversions to the alternative list 863 void Finder::addAnonConversions( const CandidateRef & cand ) { 864 // adds anonymous member interpretations whenever an aggregate value type is seen. 865 // it's okay for the aggregate expression to have reference type -- cast it to the 866 // base type to treat the aggregate as the referenced value 867 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 868 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 869 cand->env.apply( aggrType ); 870 871 if ( aggrType.as< ast::ReferenceType >() ) { 872 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; 873 } 874 875 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) { 876 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" ); 877 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 878 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" ); 879 } 880 } 881 882 /// Adds aggregate member interpretations 883 void Finder::addAggMembers( 884 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 885 const Candidate & cand, const Cost & addedCost, const std::string & name 886 ) { 887 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 888 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 889 CandidateRef newCand = std::make_shared<Candidate>( 890 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 891 // add anonymous member interpretations whenever an aggregate value type is seen 892 // as a member expression 893 addAnonConversions( newCand ); 894 candidates.emplace_back( std::move( newCand ) ); 895 } 896 } 897 898 /// Adds tuple member interpretations 899 void Finder::addTupleMembers( 900 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 901 const Cost & addedCost, const ast::Expr * member 902 ) { 903 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 904 // get the value of the constant expression as an int, must be between 0 and the 905 // length of the tuple to have meaning 906 long long val = constantExpr->intValue(); 907 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 908 addCandidate( 909 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 910 addedCost ); 911 } 912 } 913 } 914 915 void Finder::postvisit( const ast::UntypedExpr * untypedExpr ) { 916 std::vector< CandidateFinder > argCandidates = 917 selfFinder.findSubExprs( untypedExpr->args ); 918 919 // take care of possible tuple assignments 920 // if not tuple assignment, handled as normal function call 921 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates ); 922 923 CandidateFinder funcFinder( context, tenv ); 924 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) { 925 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 926 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 927 assertf(!argCandidates.empty(), "special function call without argument"); 928 for (auto & firstArgCand: argCandidates[0]) { 929 ast::ptr<ast::Type> argType = firstArgCand->expr->result; 930 firstArgCand->env.apply(argType); 931 // strip references 932 // xxx - is this correct? 933 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base; 934 935 // convert 1-tuple to plain type 936 if (auto tuple = argType.as<ast::TupleType>()) { 937 if (tuple->size() == 1) { 938 argType = tuple->types[0]; 939 } 940 } 941 942 // if argType is an unbound type parameter, all special functions need to be searched. 943 if (isUnboundType(argType)) { 944 funcFinder.otypeKeys.clear(); 945 break; 946 } 947 948 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer); 949 // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) { 950 // const ast::EnumDecl * enumDecl = enumInst->base; // Here 951 // if ( const ast::Type* enumType = enumDecl->base ) { 952 // // instance of enum (T) is a instance of type (T) 953 // funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type)); 954 // } else { 955 // // instance of an untyped enum is techically int 956 // funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type)); 957 // } 958 // } 959 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type)); 960 } 961 } 962 } 963 // if candidates are already produced, do not fail 964 // xxx - is it possible that handleTupleAssignment and main finder both produce candidates? 965 // this means there exists ctor/assign functions with a tuple as first parameter. 966 ResolvMode mode = { 967 true, // adjust 968 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name 969 selfFinder.candidates.empty() // failfast if other options are not found 970 }; 971 funcFinder.find( untypedExpr->func, mode ); 972 // short-circuit if no candidates 973 // if ( funcFinder.candidates.empty() ) return; 974 975 reason.code = NoMatch; 976 977 // find function operators 978 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{} 979 CandidateFinder opFinder( context, tenv ); 980 // okay if there aren't any function operations 981 opFinder.find( opExpr, ResolvMode::withoutFailFast() ); 982 PRINT( 983 std::cerr << "known function ops:" << std::endl; 984 print( std::cerr, opFinder.candidates, 1 ); 985 ) 986 987 // pre-explode arguments 988 ExplodedArgs_new argExpansions; 989 for ( const CandidateFinder & args : argCandidates ) { 990 argExpansions.emplace_back(); 991 auto & argE = argExpansions.back(); 992 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); } 993 } 994 995 // Find function matches 996 CandidateList found; 997 SemanticErrorException errors; 998 for ( CandidateRef & func : funcFinder ) { 999 try { 1000 PRINT( 1001 std::cerr << "working on alternative:" << std::endl; 1002 print( std::cerr, *func, 2 ); 1003 ) 1004 1005 // check if the type is a pointer to function 1006 const ast::Type * funcResult = func->expr->result->stripReferences(); 1007 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) { 1008 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 1009 CandidateRef newFunc{ new Candidate{ *func } }; 1010 newFunc->expr = 1011 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 1012 makeFunctionCandidates( untypedExpr->location, 1013 newFunc, function, argExpansions, found ); 1014 } 1015 } else if ( 1016 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 1017 ) { 1018 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) { 1019 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 1020 CandidateRef newFunc{ new Candidate{ *func } }; 1021 newFunc->expr = 1022 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 1023 makeFunctionCandidates( untypedExpr->location, 1024 newFunc, function, argExpansions, found ); 1025 } 1026 } 1027 } 1028 } catch ( SemanticErrorException & e ) { errors.append( e ); } 1029 } 1030 1031 // Find matches on function operators `?()` 1032 if ( ! opFinder.candidates.empty() ) { 1033 // add exploded function alternatives to front of argument list 1034 std::vector< ExplodedArg > funcE; 1035 funcE.reserve( funcFinder.candidates.size() ); 1036 for ( const CandidateRef & func : funcFinder ) { 1037 funcE.emplace_back( *func, symtab ); 1038 } 1039 argExpansions.emplace_front( std::move( funcE ) ); 1040 1041 for ( const CandidateRef & op : opFinder ) { 1042 try { 1043 // check if type is pointer-to-function 1044 const ast::Type * opResult = op->expr->result->stripReferences(); 1045 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) { 1046 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 1047 CandidateRef newOp{ new Candidate{ *op} }; 1048 newOp->expr = 1049 referenceToRvalueConversion( newOp->expr, newOp->cost ); 1050 makeFunctionCandidates( untypedExpr->location, 1051 newOp, function, argExpansions, found ); 1052 } 1053 } 1054 } catch ( SemanticErrorException & e ) { errors.append( e ); } 1055 } 1056 } 1057 1058 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 1059 // candidates 1060 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } 1061 1062 // Compute conversion costs 1063 for ( CandidateRef & withFunc : found ) { 1064 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab ); 1065 1066 PRINT( 1067 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >(); 1068 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 1069 auto function = pointer->base.strict_as< ast::FunctionType >(); 1070 1071 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 1072 std::cerr << "parameters are:" << std::endl; 1073 ast::printAll( std::cerr, function->params, 2 ); 1074 std::cerr << "arguments are:" << std::endl; 1075 ast::printAll( std::cerr, appExpr->args, 2 ); 1076 std::cerr << "bindings are:" << std::endl; 1077 ast::print( std::cerr, withFunc->env, 2 ); 1078 std::cerr << "cost is: " << withFunc->cost << std::endl; 1079 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1080 ) 1081 1082 if ( cvtCost != Cost::infinity ) { 1083 withFunc->cvtCost = cvtCost; 1084 candidates.emplace_back( std::move( withFunc ) ); 1085 } 1086 } 1087 found = std::move( candidates ); 1088 1089 // use a new list so that candidates are not examined by addAnonConversions twice 1090 CandidateList winners = findMinCost( found ); 1091 promoteCvtCost( winners ); 1092 1093 // function may return a struct/union value, in which case we need to add candidates 1094 // for implicit conversions to each of the anonymous members, which must happen after 1095 // `findMinCost`, since anon conversions are never the cheapest 1096 for ( const CandidateRef & c : winners ) { 1097 addAnonConversions( c ); 1098 } 1099 spliceBegin( candidates, winners ); 1100 1101 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 1102 // If resolution is unsuccessful with a target type, try again without, since it 1103 // will sometimes succeed when it wouldn't with a target type binding. 1104 // For example: 1105 // forall( otype T ) T & ?[]( T *, ptrdiff_t ); 1106 // const char * x = "hello world"; 1107 // unsigned char ch = x[0]; 1108 // Fails with simple return type binding (xxx -- check this!) as follows: 1109 // * T is bound to unsigned char 1110 // * (x: const char *) is unified with unsigned char *, which fails 1111 // xxx -- fix this better 1112 targetType = nullptr; 1113 postvisit( untypedExpr ); 1114 } 1115 } 1116 1117 void Finder::postvisit( const ast::AddressExpr * addressExpr ) { 1118 CandidateFinder finder( context, tenv ); 1119 finder.find( addressExpr->arg ); 1120 1121 if ( finder.candidates.empty() ) return; 1122 1123 reason.code = NoMatch; 1124 1125 for ( CandidateRef & r : finder.candidates ) { 1126 if ( ! isLvalue( r->expr ) ) continue; 1127 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } ); 1128 } 1129 } 1130 1131 void Finder::postvisit( const ast::LabelAddressExpr * labelExpr ) { 1132 addCandidate( labelExpr, tenv ); 1133 } 1134 1135 void Finder::postvisit( const ast::CastExpr * castExpr ) { 1136 ast::ptr< ast::Type > toType = castExpr->result; 1137 assert( toType ); 1138 toType = resolveTypeof( toType, context ); 1139 toType = adjustExprType( toType, tenv, symtab ); 1140 1141 CandidateFinder finder( context, tenv, toType ); 1142 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1143 1144 if ( !finder.candidates.empty() ) reason.code = NoMatch; 1145 1146 CandidateList matches; 1147 for ( CandidateRef & cand : finder.candidates ) { 1148 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; 1149 ast::OpenVarSet open( cand->open ); 1150 1151 cand->env.extractOpenVars( open ); 1152 1153 // It is possible that a cast can throw away some values in a multiply-valued 1154 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1155 // subexpression results that are cast directly. The candidate is invalid if it 1156 // has fewer results than there are types to cast to. 1157 int discardedValues = cand->expr->result->size() - toType->size(); 1158 if ( discardedValues < 0 ) continue; 1159 1160 // unification run for side-effects 1161 unify( toType, cand->expr->result, cand->env, need, have, open, symtab ); 1162 Cost thisCost = 1163 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast) 1164 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1165 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1166 1167 PRINT( 1168 std::cerr << "working on cast with result: " << toType << std::endl; 1169 std::cerr << "and expr type: " << cand->expr->result << std::endl; 1170 std::cerr << "env: " << cand->env << std::endl; 1171 ) 1172 if ( thisCost != Cost::infinity ) { 1173 PRINT( 1174 std::cerr << "has finite cost." << std::endl; 1175 ) 1176 // count one safe conversion for each value that is thrown away 1177 thisCost.incSafe( discardedValues ); 1178 CandidateRef newCand = std::make_shared<Candidate>( 1179 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1180 copy( cand->env ), std::move( open ), std::move( need ), cand->cost, 1181 cand->cost + thisCost ); 1182 inferParameters( newCand, matches ); 1183 } 1184 } 1185 1186 // select first on argument cost, then conversion cost 1187 CandidateList minArgCost = findMinCost( matches ); 1188 promoteCvtCost( minArgCost ); 1189 candidates = findMinCost( minArgCost ); 1190 } 1191 1192 void Finder::postvisit( const ast::VirtualCastExpr * castExpr ) { 1193 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." ); 1194 CandidateFinder finder( context, tenv ); 1195 // don't prune here, all alternatives guaranteed to have same type 1196 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1197 for ( CandidateRef & r : finder.candidates ) { 1198 addCandidate( 1199 *r, 1200 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1201 } 1202 } 1203 1204 void Finder::postvisit( const ast::KeywordCastExpr * castExpr ) { 1205 const auto & loc = castExpr->location; 1206 assertf( castExpr->result, "Cast target should have been set in Validate." ); 1207 auto ref = castExpr->result.strict_as<ast::ReferenceType>(); 1208 auto inst = ref->base.strict_as<ast::StructInstType>(); 1209 auto target = inst->base.get(); 1210 1211 CandidateFinder finder( context, tenv ); 1212 1213 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) { 1214 for (auto & cand : found) { 1215 const ast::Type * expr = cand->expr->result.get(); 1216 if (expect_ref) { 1217 auto res = dynamic_cast<const ast::ReferenceType*>(expr); 1218 if (!res) { continue; } 1219 expr = res->base.get(); 1220 } 1221 1222 if (auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) { 1223 auto td = cand->env.lookup(*insttype); 1224 if (!td) { continue; } 1225 expr = td->bound.get(); 1226 } 1227 1228 if (auto base = dynamic_cast<const ast::StructInstType*>(expr)) { 1229 if (base->base == target) { 1230 candidates.push_back( std::move(cand) ); 1231 reason.code = NoReason; 1232 } 1233 } 1234 } 1235 }; 1236 1237 try { 1238 // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd 1239 // Clone is purely for memory management 1240 std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) }; 1241 1242 // don't prune here, since it's guaranteed all alternatives will have the same type 1243 finder.find( tech1.get(), ResolvMode::withoutPrune() ); 1244 pick_alternatives(finder.candidates, false); 1245 1246 return; 1247 } catch(SemanticErrorException & ) {} 1248 1249 // Fallback : turn (thread&)X into (thread$&)get_thread(X) 1250 std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc, new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) }; 1251 // don't prune here, since it's guaranteed all alternatives will have the same type 1252 finder.find( fallback.get(), ResolvMode::withoutPrune() ); 1253 1254 pick_alternatives(finder.candidates, true); 1255 1256 // Whatever happens here, we have no more fallbacks 1257 } 1258 1259 void Finder::postvisit( const ast::UntypedMemberExpr * memberExpr ) { 1260 CandidateFinder aggFinder( context, tenv ); 1261 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1262 for ( CandidateRef & agg : aggFinder.candidates ) { 1263 // it's okay for the aggregate expression to have reference type -- cast it to the 1264 // base type to treat the aggregate as the referenced value 1265 Cost addedCost = Cost::zero; 1266 agg->expr = referenceToRvalueConversion( agg->expr, addedCost ); 1267 1268 // find member of the given type 1269 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1270 addAggMembers( 1271 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1272 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1273 addAggMembers( 1274 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1275 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { 1276 addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member ); 1277 } 1278 } 1279 } 1280 1281 void Finder::postvisit( const ast::MemberExpr * memberExpr ) { 1282 addCandidate( memberExpr, tenv ); 1283 } 1284 1285 void Finder::postvisit( const ast::NameExpr * nameExpr ) { 1286 std::vector< ast::SymbolTable::IdData > declList; 1287 if (!selfFinder.otypeKeys.empty()) { 1288 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 1289 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str()); 1290 1291 for (auto & otypeKey: selfFinder.otypeKeys) { 1292 auto result = symtab.specialLookupId(kind, otypeKey); 1293 declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end())); 1294 } 1295 } else { 1296 declList = symtab.lookupId( nameExpr->name ); 1297 } 1298 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1299 1300 if ( declList.empty() ) return; 1301 1302 reason.code = NoMatch; 1303 1304 for ( auto & data : declList ) { 1305 Cost cost = Cost::zero; 1306 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1307 1308 CandidateRef newCand = std::make_shared<Candidate>( 1309 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1310 cost ); 1311 1312 if (newCand->expr->env) { 1313 newCand->env.add(*newCand->expr->env); 1314 auto mutExpr = newCand->expr.get_and_mutate(); 1315 mutExpr->env = nullptr; 1316 newCand->expr = mutExpr; 1317 } 1318 1319 PRINT( 1320 std::cerr << "decl is "; 1321 ast::print( std::cerr, data.id ); 1322 std::cerr << std::endl; 1323 std::cerr << "newExpr is "; 1324 ast::print( std::cerr, newExpr ); 1325 std::cerr << std::endl; 1326 ) 1327 newCand->expr = ast::mutate_field( 1328 newCand->expr.get(), &ast::Expr::result, 1329 renameTyVars( newCand->expr->result ) ); 1330 // add anonymous member interpretations whenever an aggregate value type is seen 1331 // as a name expression 1332 addAnonConversions( newCand ); 1333 candidates.emplace_back( std::move( newCand ) ); 1334 } 1335 } 1336 1337 void Finder::postvisit( const ast::VariableExpr * variableExpr ) { 1338 // not sufficient to just pass `variableExpr` here, type might have changed since 1339 // creation 1340 addCandidate( 1341 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1342 } 1343 1344 void Finder::postvisit( const ast::ConstantExpr * constantExpr ) { 1345 addCandidate( constantExpr, tenv ); 1346 } 1347 1348 void Finder::postvisit( const ast::SizeofExpr * sizeofExpr ) { 1349 if ( sizeofExpr->type ) { 1350 addCandidate( 1351 new ast::SizeofExpr{ 1352 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) }, 1353 tenv ); 1354 } else { 1355 // find all candidates for the argument to sizeof 1356 CandidateFinder finder( context, tenv ); 1357 finder.find( sizeofExpr->expr ); 1358 // find the lowest-cost candidate, otherwise ambiguous 1359 CandidateList winners = findMinCost( finder.candidates ); 1360 if ( winners.size() != 1 ) { 1361 SemanticError( 1362 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1363 } 1364 // return the lowest-cost candidate 1365 CandidateRef & choice = winners.front(); 1366 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1367 choice->cost = Cost::zero; 1368 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } ); 1369 } 1370 } 1371 1372 void Finder::postvisit( const ast::AlignofExpr * alignofExpr ) { 1373 if ( alignofExpr->type ) { 1374 addCandidate( 1375 new ast::AlignofExpr{ 1376 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) }, 1377 tenv ); 1378 } else { 1379 // find all candidates for the argument to alignof 1380 CandidateFinder finder( context, tenv ); 1381 finder.find( alignofExpr->expr ); 1382 // find the lowest-cost candidate, otherwise ambiguous 1383 CandidateList winners = findMinCost( finder.candidates ); 1384 if ( winners.size() != 1 ) { 1385 SemanticError( 1386 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1387 } 1388 // return the lowest-cost candidate 1389 CandidateRef & choice = winners.front(); 1390 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1391 choice->cost = Cost::zero; 1392 addCandidate( 1393 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1394 } 1395 } 1396 1397 void Finder::postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) { 1398 const ast::BaseInstType * aggInst; 1399 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ; 1400 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ; 1401 else return; 1402 1403 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1404 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1405 addCandidate( 1406 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1407 } 1408 } 1409 1410 void Finder::postvisit( const ast::OffsetofExpr * offsetofExpr ) { 1411 addCandidate( offsetofExpr, tenv ); 1412 } 1413 1414 void Finder::postvisit( const ast::OffsetPackExpr * offsetPackExpr ) { 1415 addCandidate( offsetPackExpr, tenv ); 1416 } 1417 1418 void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) { 1419 CandidateFinder finder1( context, tenv ); 1420 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() ); 1421 if ( finder1.candidates.empty() ) return; 1422 1423 CandidateFinder finder2( context, tenv ); 1424 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1425 if ( finder2.candidates.empty() ) return; 1426 1427 reason.code = NoMatch; 1428 1429 for ( const CandidateRef & r1 : finder1.candidates ) { 1430 for ( const CandidateRef & r2 : finder2.candidates ) { 1431 ast::TypeEnvironment env{ r1->env }; 1432 env.simpleCombine( r2->env ); 1433 ast::OpenVarSet open{ r1->open }; 1434 mergeOpenVars( open, r2->open ); 1435 ast::AssertionSet need; 1436 mergeAssertionSet( need, r1->need ); 1437 mergeAssertionSet( need, r2->need ); 1438 1439 addCandidate( 1440 new ast::LogicalExpr{ 1441 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1442 std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost ); 1443 } 1444 } 1445 } 1446 1447 void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1448 // candidates for condition 1449 CandidateFinder finder1( context, tenv ); 1450 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() ); 1451 if ( finder1.candidates.empty() ) return; 1452 1453 // candidates for true result 1454 CandidateFinder finder2( context, tenv ); 1455 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1456 if ( finder2.candidates.empty() ) return; 1457 1458 // candidates for false result 1459 CandidateFinder finder3( context, tenv ); 1460 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1461 if ( finder3.candidates.empty() ) return; 1462 1463 reason.code = NoMatch; 1464 1465 for ( const CandidateRef & r1 : finder1.candidates ) { 1466 for ( const CandidateRef & r2 : finder2.candidates ) { 1467 for ( const CandidateRef & r3 : finder3.candidates ) { 1468 ast::TypeEnvironment env{ r1->env }; 1469 env.simpleCombine( r2->env ); 1470 env.simpleCombine( r3->env ); 1471 ast::OpenVarSet open{ r1->open }; 1472 mergeOpenVars( open, r2->open ); 1473 mergeOpenVars( open, r3->open ); 1474 ast::AssertionSet need; 1475 mergeAssertionSet( need, r1->need ); 1476 mergeAssertionSet( need, r2->need ); 1477 mergeAssertionSet( need, r3->need ); 1478 ast::AssertionSet have; 1479 1480 // unify true and false results, then infer parameters to produce new 1481 // candidates 1482 ast::ptr< ast::Type > common; 1483 if ( 1484 unify( 1485 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1486 common ) 1487 ) { 1488 // generate typed expression 1489 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1490 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1491 newExpr->result = common ? common : r2->expr->result; 1492 // convert both options to result type 1493 Cost cost = r1->cost + r2->cost + r3->cost; 1494 newExpr->arg2 = computeExpressionConversionCost( 1495 newExpr->arg2, newExpr->result, symtab, env, cost ); 1496 newExpr->arg3 = computeExpressionConversionCost( 1497 newExpr->arg3, newExpr->result, symtab, env, cost ); 1498 // output candidate 1499 CandidateRef newCand = std::make_shared<Candidate>( 1500 newExpr, std::move( env ), std::move( open ), std::move( need ), cost ); 1501 inferParameters( newCand, candidates ); 1502 } 1503 } 1504 } 1505 } 1506 } 1507 1508 void Finder::postvisit( const ast::CommaExpr * commaExpr ) { 1509 ast::TypeEnvironment env{ tenv }; 1510 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env ); 1511 1512 CandidateFinder finder2( context, env ); 1513 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); 1514 1515 for ( const CandidateRef & r2 : finder2.candidates ) { 1516 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } ); 1517 } 1518 } 1519 1520 void Finder::postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) { 1521 addCandidate( ctorExpr, tenv ); 1522 } 1523 1524 void Finder::postvisit( const ast::ConstructorExpr * ctorExpr ) { 1525 CandidateFinder finder( context, tenv ); 1526 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 1527 for ( CandidateRef & r : finder.candidates ) { 1528 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } ); 1529 } 1530 } 1531 1532 void Finder::postvisit( const ast::RangeExpr * rangeExpr ) { 1533 // resolve low and high, accept candidates where low and high types unify 1534 CandidateFinder finder1( context, tenv ); 1535 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() ); 1536 if ( finder1.candidates.empty() ) return; 1537 1538 CandidateFinder finder2( context, tenv ); 1539 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1540 if ( finder2.candidates.empty() ) return; 1541 1542 reason.code = NoMatch; 1543 1544 for ( const CandidateRef & r1 : finder1.candidates ) { 1545 for ( const CandidateRef & r2 : finder2.candidates ) { 1546 ast::TypeEnvironment env{ r1->env }; 1547 env.simpleCombine( r2->env ); 1548 ast::OpenVarSet open{ r1->open }; 1549 mergeOpenVars( open, r2->open ); 1550 ast::AssertionSet need; 1551 mergeAssertionSet( need, r1->need ); 1552 mergeAssertionSet( need, r2->need ); 1553 ast::AssertionSet have; 1554 1555 ast::ptr< ast::Type > common; 1556 if ( 1557 unify( 1558 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1559 common ) 1560 ) { 1561 // generate new expression 1562 ast::RangeExpr * newExpr = 1563 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1564 newExpr->result = common ? common : r1->expr->result; 1565 // add candidate 1566 CandidateRef newCand = std::make_shared<Candidate>( 1567 newExpr, std::move( env ), std::move( open ), std::move( need ), 1568 r1->cost + r2->cost ); 1569 inferParameters( newCand, candidates ); 1570 } 1571 } 1572 } 1573 } 1574 1575 void Finder::postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1576 std::vector< CandidateFinder > subCandidates = 1577 selfFinder.findSubExprs( tupleExpr->exprs ); 1578 std::vector< CandidateList > possibilities; 1579 combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) ); 1580 1581 for ( const CandidateList & subs : possibilities ) { 1582 std::vector< ast::ptr< ast::Expr > > exprs; 1583 exprs.reserve( subs.size() ); 1584 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); } 1585 1586 ast::TypeEnvironment env; 1587 ast::OpenVarSet open; 1588 ast::AssertionSet need; 1589 for ( const CandidateRef & sub : subs ) { 1590 env.simpleCombine( sub->env ); 1591 mergeOpenVars( open, sub->open ); 1592 mergeAssertionSet( need, sub->need ); 1593 } 1594 1595 addCandidate( 1596 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) }, 1597 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) ); 1598 } 1599 } 1600 1601 void Finder::postvisit( const ast::TupleExpr * tupleExpr ) { 1602 addCandidate( tupleExpr, tenv ); 1603 } 1604 1605 void Finder::postvisit( const ast::TupleIndexExpr * tupleExpr ) { 1606 addCandidate( tupleExpr, tenv ); 1607 } 1608 1609 void Finder::postvisit( const ast::TupleAssignExpr * tupleExpr ) { 1610 addCandidate( tupleExpr, tenv ); 1611 } 1612 1613 void Finder::postvisit( const ast::UniqueExpr * unqExpr ) { 1614 CandidateFinder finder( context, tenv ); 1615 finder.find( unqExpr->expr, ResolvMode::withAdjustment() ); 1616 for ( CandidateRef & r : finder.candidates ) { 1617 // ensure that the the id is passed on so that the expressions are "linked" 1618 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } ); 1619 } 1620 } 1621 1622 void Finder::postvisit( const ast::StmtExpr * stmtExpr ) { 1623 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv ); 1624 } 1625 1626 void Finder::postvisit( const ast::UntypedInitExpr * initExpr ) { 1627 // handle each option like a cast 1628 CandidateList matches; 1629 PRINT( 1630 std::cerr << "untyped init expr: " << initExpr << std::endl; 1631 ) 1632 // O(n^2) checks of d-types with e-types 1633 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) { 1634 // calculate target type 1635 const ast::Type * toType = resolveTypeof( initAlt.type, context ); 1636 toType = adjustExprType( toType, tenv, symtab ); 1637 // The call to find must occur inside this loop, otherwise polymorphic return 1638 // types are not bound to the initialization type, since return type variables are 1639 // only open for the duration of resolving the UntypedExpr. 1640 CandidateFinder finder( context, tenv, toType ); 1641 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1642 for ( CandidateRef & cand : finder.candidates ) { 1643 if (reason.code == NotFound) reason.code = NoMatch; 1644 1645 ast::TypeEnvironment env{ cand->env }; 1646 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; 1647 ast::OpenVarSet open{ cand->open }; 1648 1649 PRINT( 1650 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1651 ) 1652 1653 // It is possible that a cast can throw away some values in a multiply-valued 1654 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1655 // the subexpression results that are cast directly. The candidate is invalid 1656 // if it has fewer results than there are types to cast to. 1657 int discardedValues = cand->expr->result->size() - toType->size(); 1658 if ( discardedValues < 0 ) continue; 1659 1660 // unification run for side-effects 1661 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab ); 1662 (void) canUnify; 1663 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1664 symtab, env ); 1665 PRINT( 1666 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1667 symtab, env ); 1668 std::cerr << "Considering initialization:"; 1669 std::cerr << std::endl << " FROM: " << cand->expr->result << std::endl; 1670 std::cerr << std::endl << " TO: " << toType << std::endl; 1671 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed"); 1672 std::cerr << std::endl << " Legacy cost " << legacyCost; 1673 std::cerr << std::endl << " New cost " << thisCost; 1674 std::cerr << std::endl; 1675 ) 1676 if ( thisCost != Cost::infinity ) { 1677 // count one safe conversion for each value that is thrown away 1678 thisCost.incSafe( discardedValues ); 1679 CandidateRef newCand = std::make_shared<Candidate>( 1680 new ast::InitExpr{ 1681 initExpr->location, restructureCast( cand->expr, toType ), 1682 initAlt.designation }, 1683 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost ); 1684 inferParameters( newCand, matches ); 1685 } 1686 } 1687 } 1688 1689 // select first on argument cost, then conversion cost 1690 CandidateList minArgCost = findMinCost( matches ); 1691 promoteCvtCost( minArgCost ); 1692 candidates = findMinCost( minArgCost ); 1693 } 1694 1695 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder"); 1696 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1697 /// return type. Skips ambiguous candidates. 1698 1699 } // anonymous namespace 1700 1701 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) { 1702 struct PruneStruct { 1703 CandidateRef candidate; 1704 bool ambiguous; 1705 1706 PruneStruct() = default; 1707 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {} 1708 }; 1709 1710 // find lowest-cost candidate for each type 1711 std::unordered_map< std::string, PruneStruct > selected; 1712 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found 1713 std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;}); 1714 for ( CandidateRef & candidate : candidates ) { 1715 std::string mangleName; 1716 { 1717 ast::ptr< ast::Type > newType = candidate->expr->result; 1718 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get()); 1719 candidate->env.apply( newType ); 1720 mangleName = Mangle::mangle( newType ); 1721 } 1722 1723 auto found = selected.find( mangleName ); 1724 if (found != selected.end() && found->second.candidate->cost < candidate->cost) { 1725 PRINT( 1726 std::cerr << "cost " << candidate->cost << " loses to " 1727 << found->second.candidate->cost << std::endl; 1728 ) 1729 continue; 1730 } 1731 1732 // xxx - when do satisfyAssertions produce more than 1 result? 1733 // this should only happen when initial result type contains 1734 // unbound type parameters, then it should never be pruned by 1735 // the previous step, since renameTyVars guarantees the mangled name 1736 // is unique. 1737 CandidateList satisfied; 1738 bool needRecomputeKey = false; 1739 if (candidate->need.empty()) { 1740 satisfied.emplace_back(candidate); 1741 } 1742 else { 1743 satisfyAssertions(candidate, context.symtab, satisfied, errors); 1744 needRecomputeKey = true; 1745 } 1746 1747 for (auto & newCand : satisfied) { 1748 // recomputes type key, if satisfyAssertions changed it 1749 if (needRecomputeKey) 1750 { 1751 ast::ptr< ast::Type > newType = newCand->expr->result; 1752 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get()); 1753 newCand->env.apply( newType ); 1754 mangleName = Mangle::mangle( newType ); 1755 } 1756 auto found = selected.find( mangleName ); 1757 if ( found != selected.end() ) { 1758 if ( newCand->cost < found->second.candidate->cost ) { 1759 PRINT( 1760 std::cerr << "cost " << newCand->cost << " beats " 1761 << found->second.candidate->cost << std::endl; 1762 ) 1763 1764 found->second = PruneStruct{ newCand }; 1765 } else if ( newCand->cost == found->second.candidate->cost ) { 1766 // if one of the candidates contains a deleted identifier, can pick the other, 1767 // since deleted expressions should not be ambiguous if there is another option 1768 // that is at least as good 1769 if ( findDeletedExpr( newCand->expr ) ) { 1770 // do nothing 1771 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 1772 } else if ( findDeletedExpr( found->second.candidate->expr ) ) { 1773 PRINT( std::cerr << "current is deleted" << std::endl; ) 1774 found->second = PruneStruct{ newCand }; 1775 } else { 1776 PRINT( std::cerr << "marking ambiguous" << std::endl; ) 1777 found->second.ambiguous = true; 1778 } 1779 } else { 1780 // xxx - can satisfyAssertions increase the cost? 1781 PRINT( 1782 std::cerr << "cost " << newCand->cost << " loses to " 1783 << found->second.candidate->cost << std::endl; 1784 ) 1785 } 1786 } else { 1787 selected.emplace_hint( found, mangleName, newCand ); 1788 } 1789 } 1790 } 1791 1792 // report unambiguous min-cost candidates 1793 // CandidateList out; 1794 for ( auto & target : selected ) { 1795 if ( target.second.ambiguous ) continue; 1796 1797 CandidateRef cand = target.second.candidate; 1798 1799 ast::ptr< ast::Type > newResult = cand->expr->result; 1800 cand->env.applyFree( newResult ); 1801 cand->expr = ast::mutate_field( 1802 cand->expr.get(), &ast::Expr::result, std::move( newResult ) ); 1803 1804 out.emplace_back( cand ); 1805 } 1806 // if everything is lost in satisfyAssertions, report the error 1807 return !selected.empty(); 1808 } 1809 1810 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) { 1811 // Find alternatives for expression 1812 ast::Pass<Finder> finder{ *this }; 1813 expr->accept( finder ); 1814 1815 if ( mode.failFast && candidates.empty() ) { 1816 switch(finder.core.reason.code) { 1817 case Finder::NotFound: 1818 { SemanticError( expr, "No alternatives for expression " ); break; } 1819 case Finder::NoMatch: 1820 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; } 1821 case Finder::ArgsToFew: 1822 case Finder::ArgsToMany: 1823 case Finder::RetsToFew: 1824 case Finder::RetsToMany: 1825 case Finder::NoReason: 1826 default: 1827 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); } 1828 } 1829 } 1830 1831 /* 1832 if ( mode.satisfyAssns || mode.prune ) { 1833 // trim candidates to just those where the assertions are satisfiable 1834 // - necessary pre-requisite to pruning 1835 CandidateList satisfied; 1836 std::vector< std::string > errors; 1837 for ( CandidateRef & candidate : candidates ) { 1838 satisfyAssertions( candidate, localSyms, satisfied, errors ); 1839 } 1840 1841 // fail early if none such 1842 if ( mode.failFast && satisfied.empty() ) { 1843 std::ostringstream stream; 1844 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 1845 for ( const auto& err : errors ) { 1846 stream << err; 1847 } 1848 SemanticError( expr->location, stream.str() ); 1849 } 1850 1851 // reset candidates 1852 candidates = move( satisfied ); 1853 } 1854 */ 1855 1856 if ( mode.prune ) { 1857 // trim candidates to single best one 1858 PRINT( 1859 std::cerr << "alternatives before prune:" << std::endl; 1860 print( std::cerr, candidates ); 1861 ) 1862 1863 CandidateList pruned; 1864 std::vector<std::string> errors; 1865 bool found = pruneCandidates( candidates, pruned, errors ); 1866 1867 if ( mode.failFast && pruned.empty() ) { 1868 std::ostringstream stream; 1869 if (found) { 1870 CandidateList winners = findMinCost( candidates ); 1871 stream << "Cannot choose between " << winners.size() << " alternatives for " 1872 "expression\n"; 1873 ast::print( stream, expr ); 1874 stream << " Alternatives are:\n"; 1875 print( stream, winners, 1 ); 1876 SemanticError( expr->location, stream.str() ); 1877 } 1878 else { 1879 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 1880 for ( const auto& err : errors ) { 1881 stream << err; 1882 } 1883 SemanticError( expr->location, stream.str() ); 1884 } 1885 } 1886 1887 auto oldsize = candidates.size(); 1888 candidates = std::move( pruned ); 1889 1890 PRINT( 1891 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; 1892 ) 1893 PRINT( 1894 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1895 << std::endl; 1896 ) 1897 } 1898 1899 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1900 // adjusted 1901 if ( mode.adjust ) { 1902 for ( CandidateRef & r : candidates ) { 1903 r->expr = ast::mutate_field( 1904 r->expr.get(), &ast::Expr::result, 1905 adjustExprType( r->expr->result, r->env, context.symtab ) ); 1906 } 1907 } 1908 1909 // Central location to handle gcc extension keyword, etc. for all expressions 1910 for ( CandidateRef & r : candidates ) { 1911 if ( r->expr->extension != expr->extension ) { 1912 r->expr.get_and_mutate()->extension = expr->extension; 1913 } 1914 } 1915 } 1916 1917 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1918 const std::vector< ast::ptr< ast::Expr > > & xs 1919 ) { 1920 std::vector< CandidateFinder > out; 1921 1922 for ( const auto & x : xs ) { 1923 out.emplace_back( context, env ); 1924 out.back().find( x, ResolvMode::withAdjustment() ); 1925 1926 PRINT( 1927 std::cerr << "findSubExprs" << std::endl; 1928 print( std::cerr, out.back().candidates ); 1929 ) 1930 } 1931 1932 return out; 1933 } 1934 57 1935 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) { 58 1936 if ( expr->result.as< ast::ReferenceType >() ) { … … 64 1942 return expr; 65 1943 } 66 67 /// Unique identifier for matching expression resolutions to their requesting expression68 UniqueId globalResnSlot = 0;69 1944 70 1945 Cost computeConversionCost( … … 93 1968 } 94 1969 95 namespace {96 /// First index is which argument, second is which alternative, third is which exploded element97 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;98 99 /// Returns a list of alternatives with the minimum cost in the given list100 CandidateList findMinCost( const CandidateList & candidates ) {101 CandidateList out;102 Cost minCost = Cost::infinity;103 for ( const CandidateRef & r : candidates ) {104 if ( r->cost < minCost ) {105 minCost = r->cost;106 out.clear();107 out.emplace_back( r );108 } else if ( r->cost == minCost ) {109 out.emplace_back( r );110 }111 }112 return out;113 }114 115 /// Computes conversion cost for a given expression to a given type116 const ast::Expr * computeExpressionConversionCost(117 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost118 ) {119 Cost convCost = computeConversionCost(120 arg->result, paramType, arg->get_lvalue(), symtab, env );121 outCost += convCost;122 123 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires124 // conversion. Ignore poly cost for now, since this requires resolution of the cast to125 // infer parameters and this does not currently work for the reason stated below126 Cost tmpCost = convCost;127 tmpCost.incPoly( -tmpCost.get_polyCost() );128 if ( tmpCost != Cost::zero ) {129 ast::ptr< ast::Type > newType = paramType;130 env.apply( newType );131 return new ast::CastExpr{ arg, newType };132 133 // xxx - *should* be able to resolve this cast, but at the moment pointers are not134 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,135 // once this is fixed it should be possible to resolve the cast.136 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,137 // but it shouldn't be because this makes the conversion from DT* to DT* since138 // commontype(zero_t, DT*) is DT*, rather than nothing139 140 // CandidateFinder finder{ symtab, env };141 // finder.find( arg, ResolvMode::withAdjustment() );142 // assertf( finder.candidates.size() > 0,143 // "Somehow castable expression failed to find alternatives." );144 // assertf( finder.candidates.size() == 1,145 // "Somehow got multiple alternatives for known cast expression." );146 // return finder.candidates.front()->expr;147 }148 149 return arg;150 }151 152 /// Computes conversion cost for a given candidate153 Cost computeApplicationConversionCost(154 CandidateRef cand, const ast::SymbolTable & symtab155 ) {156 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();157 auto pointer = appExpr->func->result.strict_as< ast::PointerType >();158 auto function = pointer->base.strict_as< ast::FunctionType >();159 160 Cost convCost = Cost::zero;161 const auto & params = function->params;162 auto param = params.begin();163 auto & args = appExpr->args;164 165 for ( unsigned i = 0; i < args.size(); ++i ) {166 const ast::Type * argType = args[i]->result;167 PRINT(168 std::cerr << "arg expression:" << std::endl;169 ast::print( std::cerr, args[i], 2 );170 std::cerr << "--- results are" << std::endl;171 ast::print( std::cerr, argType, 2 );172 )173 174 if ( param == params.end() ) {175 if ( function->isVarArgs ) {176 convCost.incUnsafe();177 PRINT( std::cerr << "end of params with varargs function: inc unsafe: "178 << convCost << std::endl; ; )179 // convert reference-typed expressions into value-typed expressions180 cand->expr = ast::mutate_field_index(181 appExpr, &ast::ApplicationExpr::args, i,182 referenceToRvalueConversion( args[i], convCost ) );183 continue;184 } else return Cost::infinity;185 }186 187 if ( auto def = args[i].as< ast::DefaultArgExpr >() ) {188 // Default arguments should be free - don't include conversion cost.189 // Unwrap them here because they are not relevant to the rest of the system190 cand->expr = ast::mutate_field_index(191 appExpr, &ast::ApplicationExpr::args, i, def->expr );192 ++param;193 continue;194 }195 196 // mark conversion cost and also specialization cost of param type197 // const ast::Type * paramType = (*param)->get_type();198 cand->expr = ast::mutate_field_index(199 appExpr, &ast::ApplicationExpr::args, i,200 computeExpressionConversionCost(201 args[i], *param, symtab, cand->env, convCost ) );202 convCost.decSpec( specCost( *param ) );203 ++param; // can't be in for-loop update because of the continue204 }205 206 if ( param != params.end() ) return Cost::infinity;207 208 // specialization cost of return types can't be accounted for directly, it disables209 // otherwise-identical calls, like this example based on auto-newline in the I/O lib:210 //211 // forall(otype OS) {212 // void ?|?(OS&, int); // with newline213 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization214 // }215 216 // mark type variable and specialization cost of forall clause217 convCost.incVar( function->forall.size() );218 convCost.decSpec( function->assertions.size() );219 220 return convCost;221 }222 223 void makeUnifiableVars(224 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars,225 ast::AssertionSet & need226 ) {227 for ( auto & tyvar : type->forall ) {228 unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base };229 }230 for ( auto & assn : type->assertions ) {231 need[ assn ].isUsed = true;232 }233 }234 235 /// Gets a default value from an initializer, nullptr if not present236 const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) {237 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) {238 if ( auto ce = si->value.as< ast::CastExpr >() ) {239 return ce->arg.as< ast::ConstantExpr >();240 } else {241 return si->value.as< ast::ConstantExpr >();242 }243 }244 return nullptr;245 }246 247 /// State to iteratively build a match of parameter expressions to arguments248 struct ArgPack {249 std::size_t parent; ///< Index of parent pack250 ast::ptr< ast::Expr > expr; ///< The argument stored here251 Cost cost; ///< The cost of this argument252 ast::TypeEnvironment env; ///< Environment for this pack253 ast::AssertionSet need; ///< Assertions outstanding for this pack254 ast::AssertionSet have; ///< Assertions found for this pack255 ast::OpenVarSet open; ///< Open variables for this pack256 unsigned nextArg; ///< Index of next argument in arguments list257 unsigned tupleStart; ///< Number of tuples that start at this index258 unsigned nextExpl; ///< Index of next exploded element259 unsigned explAlt; ///< Index of alternative for nextExpl > 0260 261 ArgPack()262 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),263 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}264 265 ArgPack(266 const ast::TypeEnvironment & env, const ast::AssertionSet & need,267 const ast::AssertionSet & have, const ast::OpenVarSet & open )268 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),269 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}270 271 ArgPack(272 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,273 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,274 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,275 unsigned nextExpl = 0, unsigned explAlt = 0 )276 : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ),277 have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),278 nextExpl( nextExpl ), explAlt( explAlt ) {}279 280 ArgPack(281 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,282 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )283 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ),284 need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ),285 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}286 287 /// true if this pack is in the middle of an exploded argument288 bool hasExpl() const { return nextExpl > 0; }289 290 /// Gets the list of exploded candidates for this pack291 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const {292 return args[ nextArg-1 ][ explAlt ];293 }294 295 /// Ends a tuple expression, consolidating the appropriate args296 void endTuple( const std::vector< ArgPack > & packs ) {297 // add all expressions in tuple to list, summing cost298 std::deque< const ast::Expr * > exprs;299 const ArgPack * pack = this;300 if ( expr ) { exprs.emplace_front( expr ); }301 while ( pack->tupleStart == 0 ) {302 pack = &packs[pack->parent];303 exprs.emplace_front( pack->expr );304 cost += pack->cost;305 }306 // reset pack to appropriate tuple307 std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() );308 expr = new ast::TupleExpr{ expr->location, std::move( exprv ) };309 tupleStart = pack->tupleStart - 1;310 parent = pack->parent;311 }312 };313 314 /// Instantiates an argument to match a parameter, returns false if no matching results left315 bool instantiateArgument(316 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,317 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,318 unsigned nTuples = 0319 ) {320 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {321 // paramType is a TupleType -- group args into a TupleExpr322 ++nTuples;323 for ( const ast::Type * type : *tupleType ) {324 // xxx - dropping initializer changes behaviour from previous, but seems correct325 // ^^^ need to handle the case where a tuple has a default argument326 if ( ! instantiateArgument(327 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;328 nTuples = 0;329 }330 // re-constitute tuples for final generation331 for ( auto i = genStart; i < results.size(); ++i ) {332 results[i].endTuple( results );333 }334 return true;335 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {336 // paramType is a ttype, consumes all remaining arguments337 338 // completed tuples; will be spliced to end of results to finish339 std::vector< ArgPack > finalResults{};340 341 // iterate until all results completed342 std::size_t genEnd;343 ++nTuples;344 do {345 genEnd = results.size();346 347 // add another argument to results348 for ( std::size_t i = genStart; i < genEnd; ++i ) {349 unsigned nextArg = results[i].nextArg;350 351 // use next element of exploded tuple if present352 if ( results[i].hasExpl() ) {353 const ExplodedArg & expl = results[i].getExpl( args );354 355 unsigned nextExpl = results[i].nextExpl + 1;356 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }357 358 results.emplace_back(359 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),360 copy( results[i].need ), copy( results[i].have ),361 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,362 results[i].explAlt );363 364 continue;365 }366 367 // finish result when out of arguments368 if ( nextArg >= args.size() ) {369 ArgPack newResult{370 results[i].env, results[i].need, results[i].have, results[i].open };371 newResult.nextArg = nextArg;372 const ast::Type * argType = nullptr;373 374 if ( nTuples > 0 || ! results[i].expr ) {375 // first iteration or no expression to clone,376 // push empty tuple expression377 newResult.parent = i;378 newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };379 argType = newResult.expr->result;380 } else {381 // clone result to collect tuple382 newResult.parent = results[i].parent;383 newResult.cost = results[i].cost;384 newResult.tupleStart = results[i].tupleStart;385 newResult.expr = results[i].expr;386 argType = newResult.expr->result;387 388 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) {389 // the case where a ttype value is passed directly is special,390 // e.g. for argument forwarding purposes391 // xxx - what if passing multiple arguments, last of which is392 // ttype?393 // xxx - what would happen if unify was changed so that unifying394 // tuple395 // types flattened both before unifying lists? then pass in396 // TupleType (ttype) below.397 --newResult.tupleStart;398 } else {399 // collapse leftover arguments into tuple400 newResult.endTuple( results );401 argType = newResult.expr->result;402 }403 }404 405 // check unification for ttype before adding to final406 if (407 unify(408 ttype, argType, newResult.env, newResult.need, newResult.have,409 newResult.open, symtab )410 ) {411 finalResults.emplace_back( std::move( newResult ) );412 }413 414 continue;415 }416 417 // add each possible next argument418 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {419 const ExplodedArg & expl = args[nextArg][j];420 421 // fresh copies of parent parameters for this iteration422 ast::TypeEnvironment env = results[i].env;423 ast::OpenVarSet open = results[i].open;424 425 env.addActual( expl.env, open );426 427 // skip empty tuple arguments by (nearly) cloning parent into next gen428 if ( expl.exprs.empty() ) {429 results.emplace_back(430 results[i], std::move( env ), copy( results[i].need ),431 copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost );432 433 continue;434 }435 436 // add new result437 results.emplace_back(438 i, expl.exprs.front(), std::move( env ), copy( results[i].need ),439 copy( results[i].have ), std::move( open ), nextArg + 1, nTuples,440 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );441 }442 }443 444 // reset for next round445 genStart = genEnd;446 nTuples = 0;447 } while ( genEnd != results.size() );448 449 // splice final results onto results450 for ( std::size_t i = 0; i < finalResults.size(); ++i ) {451 results.emplace_back( std::move( finalResults[i] ) );452 }453 return ! finalResults.empty();454 }455 456 // iterate each current subresult457 std::size_t genEnd = results.size();458 for ( std::size_t i = genStart; i < genEnd; ++i ) {459 unsigned nextArg = results[i].nextArg;460 461 // use remainder of exploded tuple if present462 if ( results[i].hasExpl() ) {463 const ExplodedArg & expl = results[i].getExpl( args );464 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ];465 466 ast::TypeEnvironment env = results[i].env;467 ast::AssertionSet need = results[i].need, have = results[i].have;468 ast::OpenVarSet open = results[i].open;469 470 const ast::Type * argType = expr->result;471 472 PRINT(473 std::cerr << "param type is ";474 ast::print( std::cerr, paramType );475 std::cerr << std::endl << "arg type is ";476 ast::print( std::cerr, argType );477 std::cerr << std::endl;478 )479 480 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {481 unsigned nextExpl = results[i].nextExpl + 1;482 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }483 484 results.emplace_back(485 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg,486 nTuples, Cost::zero, nextExpl, results[i].explAlt );487 }488 489 continue;490 }491 492 // use default initializers if out of arguments493 if ( nextArg >= args.size() ) {494 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) {495 ast::TypeEnvironment env = results[i].env;496 ast::AssertionSet need = results[i].need, have = results[i].have;497 ast::OpenVarSet open = results[i].open;498 499 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {500 results.emplace_back(501 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),502 std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples );503 }504 }505 506 continue;507 }508 509 // Check each possible next argument510 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {511 const ExplodedArg & expl = args[nextArg][j];512 513 // fresh copies of parent parameters for this iteration514 ast::TypeEnvironment env = results[i].env;515 ast::AssertionSet need = results[i].need, have = results[i].have;516 ast::OpenVarSet open = results[i].open;517 518 env.addActual( expl.env, open );519 520 // skip empty tuple arguments by (nearly) cloning parent into next gen521 if ( expl.exprs.empty() ) {522 results.emplace_back(523 results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ),524 nextArg + 1, expl.cost );525 526 continue;527 }528 529 // consider only first exploded arg530 const ast::Expr * expr = expl.exprs.front();531 const ast::Type * argType = expr->result;532 533 PRINT(534 std::cerr << "param type is ";535 ast::print( std::cerr, paramType );536 std::cerr << std::endl << "arg type is ";537 ast::print( std::cerr, argType );538 std::cerr << std::endl;539 )540 541 // attempt to unify types542 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {543 // add new result544 results.emplace_back(545 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),546 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );547 }548 }549 }550 551 // reset for next parameter552 genStart = genEnd;553 554 return genEnd != results.size(); // were any new results added?555 }556 557 /// Generate a cast expression from `arg` to `toType`558 const ast::Expr * restructureCast(559 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast560 ) {561 if (562 arg->result->size() > 1563 && ! toType->isVoid()564 && ! dynamic_cast< const ast::ReferenceType * >( toType )565 ) {566 // Argument is a tuple and the target type is neither void nor a reference. Cast each567 // member of the tuple to its corresponding target type, producing the tuple of those568 // cast expressions. If there are more components of the tuple than components in the569 // target type, then excess components do not come out in the result expression (but570 // UniqueExpr ensures that the side effects will still be produced)571 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {572 // expressions which may contain side effects require a single unique instance of573 // the expression574 arg = new ast::UniqueExpr{ arg->location, arg };575 }576 std::vector< ast::ptr< ast::Expr > > components;577 for ( unsigned i = 0; i < toType->size(); ++i ) {578 // cast each component579 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };580 components.emplace_back(581 restructureCast( idx, toType->getComponent( i ), isGenerated ) );582 }583 return new ast::TupleExpr{ arg->location, std::move( components ) };584 } else {585 // handle normally586 return new ast::CastExpr{ arg->location, arg, toType, isGenerated };587 }588 }589 590 /// Gets the name from an untyped member expression (must be NameExpr)591 const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) {592 if ( memberExpr->member.as< ast::ConstantExpr >() ) {593 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );594 }595 596 return memberExpr->member.strict_as< ast::NameExpr >()->name;597 }598 599 /// Actually visits expressions to find their candidate interpretations600 class Finder final : public ast::WithShortCircuiting {601 const ResolveContext & context;602 const ast::SymbolTable & symtab;603 public:604 // static size_t traceId;605 CandidateFinder & selfFinder;606 CandidateList & candidates;607 const ast::TypeEnvironment & tenv;608 ast::ptr< ast::Type > & targetType;609 610 enum Errors {611 NotFound,612 NoMatch,613 ArgsToFew,614 ArgsToMany,615 RetsToFew,616 RetsToMany,617 NoReason618 };619 620 struct {621 Errors code = NotFound;622 } reason;623 624 Finder( CandidateFinder & f )625 : context( f.context ), symtab( context.symtab ), selfFinder( f ),626 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}627 628 void previsit( const ast::Node * ) { visit_children = false; }629 630 /// Convenience to add candidate to list631 template<typename... Args>632 void addCandidate( Args &&... args ) {633 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );634 reason.code = NoReason;635 }636 637 void postvisit( const ast::ApplicationExpr * applicationExpr ) {638 addCandidate( applicationExpr, tenv );639 }640 641 /// Set up candidate assertions for inference642 void inferParameters( CandidateRef & newCand, CandidateList & out ) {643 // Set need bindings for any unbound assertions644 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions645 for ( auto & assn : newCand->need ) {646 // skip already-matched assertions647 if ( assn.second.resnSlot != 0 ) continue;648 // assign slot for expression if needed649 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }650 // fix slot to assertion651 assn.second.resnSlot = crntResnSlot;652 }653 // pair slot to expression654 if ( crntResnSlot != 0 ) {655 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot );656 }657 658 // add to output list; assertion satisfaction will occur later659 out.emplace_back( newCand );660 }661 662 /// Completes a function candidate with arguments located663 void validateFunctionCandidate(664 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,665 CandidateList & out666 ) {667 ast::ApplicationExpr * appExpr =668 new ast::ApplicationExpr{ func->expr->location, func->expr };669 // sum cost and accumulate arguments670 std::deque< const ast::Expr * > args;671 Cost cost = func->cost;672 const ArgPack * pack = &result;673 while ( pack->expr ) {674 args.emplace_front( pack->expr );675 cost += pack->cost;676 pack = &results[pack->parent];677 }678 std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() );679 appExpr->args = std::move( vargs );680 // build and validate new candidate681 auto newCand =682 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );683 PRINT(684 std::cerr << "instantiate function success: " << appExpr << std::endl;685 std::cerr << "need assertions:" << std::endl;686 ast::print( std::cerr, result.need, 2 );687 )688 inferParameters( newCand, out );689 }690 691 /// Builds a list of candidates for a function, storing them in out692 void makeFunctionCandidates(693 const CandidateRef & func, const ast::FunctionType * funcType,694 const ExplodedArgs_new & args, CandidateList & out695 ) {696 ast::OpenVarSet funcOpen;697 ast::AssertionSet funcNeed, funcHave;698 ast::TypeEnvironment funcEnv{ func->env };699 makeUnifiableVars( funcType, funcOpen, funcNeed );700 // add all type variables as open variables now so that those not used in the701 // parameter list are still considered open702 funcEnv.add( funcType->forall );703 704 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {705 // attempt to narrow based on expected target type706 const ast::Type * returnType = funcType->returns.front();707 if ( ! unify(708 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )709 ) {710 // unification failed, do not pursue this candidate711 return;712 }713 }714 715 // iteratively build matches, one parameter at a time716 std::vector< ArgPack > results;717 results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen );718 std::size_t genStart = 0;719 720 // xxx - how to handle default arg after change to ftype representation?721 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {722 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {723 // function may have default args only if directly calling by name724 // must use types on candidate however, due to RenameVars substitution725 auto nParams = funcType->params.size();726 727 for (size_t i=0; i<nParams; ++i) {728 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();729 if (!instantiateArgument(730 funcType->params[i], obj->init, args, results, genStart, symtab)) return;731 }732 goto endMatch;733 }734 }735 for ( const auto & param : funcType->params ) {736 // Try adding the arguments corresponding to the current parameter to the existing737 // matches738 // no default args for indirect calls739 if ( ! instantiateArgument(740 param, nullptr, args, results, genStart, symtab ) ) return;741 }742 743 endMatch:744 if ( funcType->isVarArgs ) {745 // append any unused arguments to vararg pack746 std::size_t genEnd;747 do {748 genEnd = results.size();749 750 // iterate results751 for ( std::size_t i = genStart; i < genEnd; ++i ) {752 unsigned nextArg = results[i].nextArg;753 754 // use remainder of exploded tuple if present755 if ( results[i].hasExpl() ) {756 const ExplodedArg & expl = results[i].getExpl( args );757 758 unsigned nextExpl = results[i].nextExpl + 1;759 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }760 761 results.emplace_back(762 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),763 copy( results[i].need ), copy( results[i].have ),764 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl,765 results[i].explAlt );766 767 continue;768 }769 770 // finish result when out of arguments771 if ( nextArg >= args.size() ) {772 validateFunctionCandidate( func, results[i], results, out );773 774 continue;775 }776 777 // add each possible next argument778 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {779 const ExplodedArg & expl = args[nextArg][j];780 781 // fresh copies of parent parameters for this iteration782 ast::TypeEnvironment env = results[i].env;783 ast::OpenVarSet open = results[i].open;784 785 env.addActual( expl.env, open );786 787 // skip empty tuple arguments by (nearly) cloning parent into next gen788 if ( expl.exprs.empty() ) {789 results.emplace_back(790 results[i], std::move( env ), copy( results[i].need ),791 copy( results[i].have ), std::move( open ), nextArg + 1,792 expl.cost );793 794 continue;795 }796 797 // add new result798 results.emplace_back(799 i, expl.exprs.front(), std::move( env ), copy( results[i].need ),800 copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost,801 expl.exprs.size() == 1 ? 0 : 1, j );802 }803 }804 805 genStart = genEnd;806 } while( genEnd != results.size() );807 } else {808 // filter out the results that don't use all the arguments809 for ( std::size_t i = genStart; i < results.size(); ++i ) {810 ArgPack & result = results[i];811 if ( ! result.hasExpl() && result.nextArg >= args.size() ) {812 validateFunctionCandidate( func, result, results, out );813 }814 }815 }816 }817 818 /// Adds implicit struct-conversions to the alternative list819 void addAnonConversions( const CandidateRef & cand ) {820 // adds anonymous member interpretations whenever an aggregate value type is seen.821 // it's okay for the aggregate expression to have reference type -- cast it to the822 // base type to treat the aggregate as the referenced value823 ast::ptr< ast::Expr > aggrExpr( cand->expr );824 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;825 cand->env.apply( aggrType );826 827 if ( aggrType.as< ast::ReferenceType >() ) {828 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };829 }830 831 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {832 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" );833 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {834 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" );835 }836 }837 838 /// Adds aggregate member interpretations839 void addAggMembers(840 const ast::BaseInstType * aggrInst, const ast::Expr * expr,841 const Candidate & cand, const Cost & addedCost, const std::string & name842 ) {843 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {844 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );845 CandidateRef newCand = std::make_shared<Candidate>(846 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );847 // add anonymous member interpretations whenever an aggregate value type is seen848 // as a member expression849 addAnonConversions( newCand );850 candidates.emplace_back( std::move( newCand ) );851 }852 }853 854 /// Adds tuple member interpretations855 void addTupleMembers(856 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,857 const Cost & addedCost, const ast::Expr * member858 ) {859 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {860 // get the value of the constant expression as an int, must be between 0 and the861 // length of the tuple to have meaning862 long long val = constantExpr->intValue();863 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {864 addCandidate(865 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },866 addedCost );867 }868 }869 }870 871 void postvisit( const ast::UntypedExpr * untypedExpr ) {872 std::vector< CandidateFinder > argCandidates =873 selfFinder.findSubExprs( untypedExpr->args );874 875 // take care of possible tuple assignments876 // if not tuple assignment, handled as normal function call877 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );878 879 CandidateFinder funcFinder( context, tenv );880 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {881 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);882 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {883 assertf(!argCandidates.empty(), "special function call without argument");884 for (auto & firstArgCand: argCandidates[0]) {885 ast::ptr<ast::Type> argType = firstArgCand->expr->result;886 firstArgCand->env.apply(argType);887 // strip references888 // xxx - is this correct?889 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base;890 891 // convert 1-tuple to plain type892 if (auto tuple = argType.as<ast::TupleType>()) {893 if (tuple->size() == 1) {894 argType = tuple->types[0];895 }896 }897 898 // if argType is an unbound type parameter, all special functions need to be searched.899 if (isUnboundType(argType)) {900 funcFinder.otypeKeys.clear();901 break;902 }903 904 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);905 // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {906 // const ast::EnumDecl * enumDecl = enumInst->base; // Here907 // if ( const ast::Type* enumType = enumDecl->base ) {908 // // instance of enum (T) is a instance of type (T)909 // funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));910 // } else {911 // // instance of an untyped enum is techically int912 // funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));913 // }914 // }915 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));916 }917 }918 }919 // if candidates are already produced, do not fail920 // xxx - is it possible that handleTupleAssignment and main finder both produce candidates?921 // this means there exists ctor/assign functions with a tuple as first parameter.922 ResolvMode mode = {923 true, // adjust924 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name925 selfFinder.candidates.empty() // failfast if other options are not found926 };927 funcFinder.find( untypedExpr->func, mode );928 // short-circuit if no candidates929 // if ( funcFinder.candidates.empty() ) return;930 931 reason.code = NoMatch;932 933 // find function operators934 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{}935 CandidateFinder opFinder( context, tenv );936 // okay if there aren't any function operations937 opFinder.find( opExpr, ResolvMode::withoutFailFast() );938 PRINT(939 std::cerr << "known function ops:" << std::endl;940 print( std::cerr, opFinder.candidates, 1 );941 )942 943 // pre-explode arguments944 ExplodedArgs_new argExpansions;945 for ( const CandidateFinder & args : argCandidates ) {946 argExpansions.emplace_back();947 auto & argE = argExpansions.back();948 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); }949 }950 951 // Find function matches952 CandidateList found;953 SemanticErrorException errors;954 for ( CandidateRef & func : funcFinder ) {955 try {956 PRINT(957 std::cerr << "working on alternative:" << std::endl;958 print( std::cerr, *func, 2 );959 )960 961 // check if the type is a pointer to function962 const ast::Type * funcResult = func->expr->result->stripReferences();963 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {964 if ( auto function = pointer->base.as< ast::FunctionType >() ) {965 CandidateRef newFunc{ new Candidate{ *func } };966 newFunc->expr =967 referenceToRvalueConversion( newFunc->expr, newFunc->cost );968 makeFunctionCandidates( newFunc, function, argExpansions, found );969 }970 } else if (971 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )972 ) {973 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {974 if ( auto function = clz->bound.as< ast::FunctionType >() ) {975 CandidateRef newFunc{ new Candidate{ *func } };976 newFunc->expr =977 referenceToRvalueConversion( newFunc->expr, newFunc->cost );978 makeFunctionCandidates( newFunc, function, argExpansions, found );979 }980 }981 }982 } catch ( SemanticErrorException & e ) { errors.append( e ); }983 }984 985 // Find matches on function operators `?()`986 if ( ! opFinder.candidates.empty() ) {987 // add exploded function alternatives to front of argument list988 std::vector< ExplodedArg > funcE;989 funcE.reserve( funcFinder.candidates.size() );990 for ( const CandidateRef & func : funcFinder ) {991 funcE.emplace_back( *func, symtab );992 }993 argExpansions.emplace_front( std::move( funcE ) );994 995 for ( const CandidateRef & op : opFinder ) {996 try {997 // check if type is pointer-to-function998 const ast::Type * opResult = op->expr->result->stripReferences();999 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) {1000 if ( auto function = pointer->base.as< ast::FunctionType >() ) {1001 CandidateRef newOp{ new Candidate{ *op} };1002 newOp->expr =1003 referenceToRvalueConversion( newOp->expr, newOp->cost );1004 makeFunctionCandidates( newOp, function, argExpansions, found );1005 }1006 }1007 } catch ( SemanticErrorException & e ) { errors.append( e ); }1008 }1009 }1010 1011 // Implement SFINAE; resolution errors are only errors if there aren't any non-error1012 // candidates1013 if ( found.empty() && ! errors.isEmpty() ) { throw errors; }1014 1015 // Compute conversion costs1016 for ( CandidateRef & withFunc : found ) {1017 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );1018 1019 PRINT(1020 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();1021 auto pointer = appExpr->func->result.strict_as< ast::PointerType >();1022 auto function = pointer->base.strict_as< ast::FunctionType >();1023 1024 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;1025 std::cerr << "parameters are:" << std::endl;1026 ast::printAll( std::cerr, function->params, 2 );1027 std::cerr << "arguments are:" << std::endl;1028 ast::printAll( std::cerr, appExpr->args, 2 );1029 std::cerr << "bindings are:" << std::endl;1030 ast::print( std::cerr, withFunc->env, 2 );1031 std::cerr << "cost is: " << withFunc->cost << std::endl;1032 std::cerr << "cost of conversion is:" << cvtCost << std::endl;1033 )1034 1035 if ( cvtCost != Cost::infinity ) {1036 withFunc->cvtCost = cvtCost;1037 candidates.emplace_back( std::move( withFunc ) );1038 }1039 }1040 found = std::move( candidates );1041 1042 // use a new list so that candidates are not examined by addAnonConversions twice1043 CandidateList winners = findMinCost( found );1044 promoteCvtCost( winners );1045 1046 // function may return a struct/union value, in which case we need to add candidates1047 // for implicit conversions to each of the anonymous members, which must happen after1048 // `findMinCost`, since anon conversions are never the cheapest1049 for ( const CandidateRef & c : winners ) {1050 addAnonConversions( c );1051 }1052 spliceBegin( candidates, winners );1053 1054 if ( candidates.empty() && targetType && ! targetType->isVoid() ) {1055 // If resolution is unsuccessful with a target type, try again without, since it1056 // will sometimes succeed when it wouldn't with a target type binding.1057 // For example:1058 // forall( otype T ) T & ?[]( T *, ptrdiff_t );1059 // const char * x = "hello world";1060 // unsigned char ch = x[0];1061 // Fails with simple return type binding (xxx -- check this!) as follows:1062 // * T is bound to unsigned char1063 // * (x: const char *) is unified with unsigned char *, which fails1064 // xxx -- fix this better1065 targetType = nullptr;1066 postvisit( untypedExpr );1067 }1068 }1069 1070 /// true if expression is an lvalue1071 static bool isLvalue( const ast::Expr * x ) {1072 return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );1073 }1074 1075 void postvisit( const ast::AddressExpr * addressExpr ) {1076 CandidateFinder finder( context, tenv );1077 finder.find( addressExpr->arg );1078 1079 if( finder.candidates.empty() ) return;1080 1081 reason.code = NoMatch;1082 1083 for ( CandidateRef & r : finder.candidates ) {1084 if ( ! isLvalue( r->expr ) ) continue;1085 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } );1086 }1087 }1088 1089 void postvisit( const ast::LabelAddressExpr * labelExpr ) {1090 addCandidate( labelExpr, tenv );1091 }1092 1093 void postvisit( const ast::CastExpr * castExpr ) {1094 ast::ptr< ast::Type > toType = castExpr->result;1095 assert( toType );1096 toType = resolveTypeof( toType, context );1097 toType = adjustExprType( toType, tenv, symtab );1098 1099 CandidateFinder finder( context, tenv, toType );1100 finder.find( castExpr->arg, ResolvMode::withAdjustment() );1101 1102 if( !finder.candidates.empty() ) reason.code = NoMatch;1103 1104 CandidateList matches;1105 for ( CandidateRef & cand : finder.candidates ) {1106 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;1107 ast::OpenVarSet open( cand->open );1108 1109 cand->env.extractOpenVars( open );1110 1111 // It is possible that a cast can throw away some values in a multiply-valued1112 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the1113 // subexpression results that are cast directly. The candidate is invalid if it1114 // has fewer results than there are types to cast to.1115 int discardedValues = cand->expr->result->size() - toType->size();1116 if ( discardedValues < 0 ) continue;1117 1118 // unification run for side-effects1119 unify( toType, cand->expr->result, cand->env, need, have, open, symtab );1120 Cost thisCost =1121 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)1122 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )1123 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );1124 1125 PRINT(1126 std::cerr << "working on cast with result: " << toType << std::endl;1127 std::cerr << "and expr type: " << cand->expr->result << std::endl;1128 std::cerr << "env: " << cand->env << std::endl;1129 )1130 if ( thisCost != Cost::infinity ) {1131 PRINT(1132 std::cerr << "has finite cost." << std::endl;1133 )1134 // count one safe conversion for each value that is thrown away1135 thisCost.incSafe( discardedValues );1136 CandidateRef newCand = std::make_shared<Candidate>(1137 restructureCast( cand->expr, toType, castExpr->isGenerated ),1138 copy( cand->env ), std::move( open ), std::move( need ), cand->cost,1139 cand->cost + thisCost );1140 inferParameters( newCand, matches );1141 }1142 }1143 1144 // select first on argument cost, then conversion cost1145 CandidateList minArgCost = findMinCost( matches );1146 promoteCvtCost( minArgCost );1147 candidates = findMinCost( minArgCost );1148 }1149 1150 void postvisit( const ast::VirtualCastExpr * castExpr ) {1151 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );1152 CandidateFinder finder( context, tenv );1153 // don't prune here, all alternatives guaranteed to have same type1154 finder.find( castExpr->arg, ResolvMode::withoutPrune() );1155 for ( CandidateRef & r : finder.candidates ) {1156 addCandidate(1157 *r,1158 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );1159 }1160 }1161 1162 void postvisit( const ast::KeywordCastExpr * castExpr ) {1163 const auto & loc = castExpr->location;1164 assertf( castExpr->result, "Cast target should have been set in Validate." );1165 auto ref = castExpr->result.strict_as<ast::ReferenceType>();1166 auto inst = ref->base.strict_as<ast::StructInstType>();1167 auto target = inst->base.get();1168 1169 CandidateFinder finder( context, tenv );1170 1171 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {1172 for(auto & cand : found) {1173 const ast::Type * expr = cand->expr->result.get();1174 if(expect_ref) {1175 auto res = dynamic_cast<const ast::ReferenceType*>(expr);1176 if(!res) { continue; }1177 expr = res->base.get();1178 }1179 1180 if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {1181 auto td = cand->env.lookup(*insttype);1182 if(!td) { continue; }1183 expr = td->bound.get();1184 }1185 1186 if(auto base = dynamic_cast<const ast::StructInstType*>(expr)) {1187 if(base->base == target) {1188 candidates.push_back( std::move(cand) );1189 reason.code = NoReason;1190 }1191 }1192 }1193 };1194 1195 try {1196 // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd1197 // Clone is purely for memory management1198 std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) };1199 1200 // don't prune here, since it's guaranteed all alternatives will have the same type1201 finder.find( tech1.get(), ResolvMode::withoutPrune() );1202 pick_alternatives(finder.candidates, false);1203 1204 return;1205 } catch(SemanticErrorException & ) {}1206 1207 // Fallback : turn (thread&)X into (thread$&)get_thread(X)1208 std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc, new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) };1209 // don't prune here, since it's guaranteed all alternatives will have the same type1210 finder.find( fallback.get(), ResolvMode::withoutPrune() );1211 1212 pick_alternatives(finder.candidates, true);1213 1214 // Whatever happens here, we have no more fallbacks1215 }1216 1217 void postvisit( const ast::UntypedMemberExpr * memberExpr ) {1218 CandidateFinder aggFinder( context, tenv );1219 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );1220 for ( CandidateRef & agg : aggFinder.candidates ) {1221 // it's okay for the aggregate expression to have reference type -- cast it to the1222 // base type to treat the aggregate as the referenced value1223 Cost addedCost = Cost::zero;1224 agg->expr = referenceToRvalueConversion( agg->expr, addedCost );1225 1226 // find member of the given type1227 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {1228 addAggMembers(1229 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );1230 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {1231 addAggMembers(1232 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );1233 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {1234 addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member );1235 }1236 }1237 }1238 1239 void postvisit( const ast::MemberExpr * memberExpr ) {1240 addCandidate( memberExpr, tenv );1241 }1242 1243 void postvisit( const ast::NameExpr * nameExpr ) {1244 std::vector< ast::SymbolTable::IdData > declList;1245 if (!selfFinder.otypeKeys.empty()) {1246 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);1247 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str());1248 1249 for (auto & otypeKey: selfFinder.otypeKeys) {1250 auto result = symtab.specialLookupId(kind, otypeKey);1251 declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end()));1252 }1253 }1254 else {1255 declList = symtab.lookupId( nameExpr->name );1256 }1257 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )1258 1259 if( declList.empty() ) return;1260 1261 reason.code = NoMatch;1262 1263 for ( auto & data : declList ) {1264 Cost cost = Cost::zero;1265 ast::Expr * newExpr = data.combine( nameExpr->location, cost );1266 1267 CandidateRef newCand = std::make_shared<Candidate>(1268 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,1269 cost );1270 1271 if (newCand->expr->env) {1272 newCand->env.add(*newCand->expr->env);1273 auto mutExpr = newCand->expr.get_and_mutate();1274 mutExpr->env = nullptr;1275 newCand->expr = mutExpr;1276 }1277 1278 PRINT(1279 std::cerr << "decl is ";1280 ast::print( std::cerr, data.id );1281 std::cerr << std::endl;1282 std::cerr << "newExpr is ";1283 ast::print( std::cerr, newExpr );1284 std::cerr << std::endl;1285 )1286 newCand->expr = ast::mutate_field(1287 newCand->expr.get(), &ast::Expr::result,1288 renameTyVars( newCand->expr->result ) );1289 // add anonymous member interpretations whenever an aggregate value type is seen1290 // as a name expression1291 addAnonConversions( newCand );1292 candidates.emplace_back( std::move( newCand ) );1293 }1294 }1295 1296 void postvisit( const ast::VariableExpr * variableExpr ) {1297 // not sufficient to just pass `variableExpr` here, type might have changed since1298 // creation1299 addCandidate(1300 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );1301 }1302 1303 void postvisit( const ast::ConstantExpr * constantExpr ) {1304 addCandidate( constantExpr, tenv );1305 }1306 1307 void postvisit( const ast::SizeofExpr * sizeofExpr ) {1308 if ( sizeofExpr->type ) {1309 addCandidate(1310 new ast::SizeofExpr{1311 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },1312 tenv );1313 } else {1314 // find all candidates for the argument to sizeof1315 CandidateFinder finder( context, tenv );1316 finder.find( sizeofExpr->expr );1317 // find the lowest-cost candidate, otherwise ambiguous1318 CandidateList winners = findMinCost( finder.candidates );1319 if ( winners.size() != 1 ) {1320 SemanticError(1321 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );1322 }1323 // return the lowest-cost candidate1324 CandidateRef & choice = winners.front();1325 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );1326 choice->cost = Cost::zero;1327 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } );1328 }1329 }1330 1331 void postvisit( const ast::AlignofExpr * alignofExpr ) {1332 if ( alignofExpr->type ) {1333 addCandidate(1334 new ast::AlignofExpr{1335 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },1336 tenv );1337 } else {1338 // find all candidates for the argument to alignof1339 CandidateFinder finder( context, tenv );1340 finder.find( alignofExpr->expr );1341 // find the lowest-cost candidate, otherwise ambiguous1342 CandidateList winners = findMinCost( finder.candidates );1343 if ( winners.size() != 1 ) {1344 SemanticError(1345 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );1346 }1347 // return the lowest-cost candidate1348 CandidateRef & choice = winners.front();1349 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );1350 choice->cost = Cost::zero;1351 addCandidate(1352 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );1353 }1354 }1355 1356 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {1357 const ast::BaseInstType * aggInst;1358 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;1359 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;1360 else return;1361 1362 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {1363 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );1364 addCandidate(1365 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );1366 }1367 }1368 1369 void postvisit( const ast::OffsetofExpr * offsetofExpr ) {1370 addCandidate( offsetofExpr, tenv );1371 }1372 1373 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ) {1374 addCandidate( offsetPackExpr, tenv );1375 }1376 1377 void postvisit( const ast::LogicalExpr * logicalExpr ) {1378 CandidateFinder finder1( context, tenv );1379 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );1380 if ( finder1.candidates.empty() ) return;1381 1382 CandidateFinder finder2( context, tenv );1383 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );1384 if ( finder2.candidates.empty() ) return;1385 1386 reason.code = NoMatch;1387 1388 for ( const CandidateRef & r1 : finder1.candidates ) {1389 for ( const CandidateRef & r2 : finder2.candidates ) {1390 ast::TypeEnvironment env{ r1->env };1391 env.simpleCombine( r2->env );1392 ast::OpenVarSet open{ r1->open };1393 mergeOpenVars( open, r2->open );1394 ast::AssertionSet need;1395 mergeAssertionSet( need, r1->need );1396 mergeAssertionSet( need, r2->need );1397 1398 addCandidate(1399 new ast::LogicalExpr{1400 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },1401 std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost );1402 }1403 }1404 }1405 1406 void postvisit( const ast::ConditionalExpr * conditionalExpr ) {1407 // candidates for condition1408 CandidateFinder finder1( context, tenv );1409 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );1410 if ( finder1.candidates.empty() ) return;1411 1412 // candidates for true result1413 CandidateFinder finder2( context, tenv );1414 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );1415 if ( finder2.candidates.empty() ) return;1416 1417 // candidates for false result1418 CandidateFinder finder3( context, tenv );1419 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );1420 if ( finder3.candidates.empty() ) return;1421 1422 reason.code = NoMatch;1423 1424 for ( const CandidateRef & r1 : finder1.candidates ) {1425 for ( const CandidateRef & r2 : finder2.candidates ) {1426 for ( const CandidateRef & r3 : finder3.candidates ) {1427 ast::TypeEnvironment env{ r1->env };1428 env.simpleCombine( r2->env );1429 env.simpleCombine( r3->env );1430 ast::OpenVarSet open{ r1->open };1431 mergeOpenVars( open, r2->open );1432 mergeOpenVars( open, r3->open );1433 ast::AssertionSet need;1434 mergeAssertionSet( need, r1->need );1435 mergeAssertionSet( need, r2->need );1436 mergeAssertionSet( need, r3->need );1437 ast::AssertionSet have;1438 1439 // unify true and false results, then infer parameters to produce new1440 // candidates1441 ast::ptr< ast::Type > common;1442 if (1443 unify(1444 r2->expr->result, r3->expr->result, env, need, have, open, symtab,1445 common )1446 ) {1447 // generate typed expression1448 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{1449 conditionalExpr->location, r1->expr, r2->expr, r3->expr };1450 newExpr->result = common ? common : r2->expr->result;1451 // convert both options to result type1452 Cost cost = r1->cost + r2->cost + r3->cost;1453 newExpr->arg2 = computeExpressionConversionCost(1454 newExpr->arg2, newExpr->result, symtab, env, cost );1455 newExpr->arg3 = computeExpressionConversionCost(1456 newExpr->arg3, newExpr->result, symtab, env, cost );1457 // output candidate1458 CandidateRef newCand = std::make_shared<Candidate>(1459 newExpr, std::move( env ), std::move( open ), std::move( need ), cost );1460 inferParameters( newCand, candidates );1461 }1462 }1463 }1464 }1465 }1466 1467 void postvisit( const ast::CommaExpr * commaExpr ) {1468 ast::TypeEnvironment env{ tenv };1469 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );1470 1471 CandidateFinder finder2( context, env );1472 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );1473 1474 for ( const CandidateRef & r2 : finder2.candidates ) {1475 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } );1476 }1477 }1478 1479 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) {1480 addCandidate( ctorExpr, tenv );1481 }1482 1483 void postvisit( const ast::ConstructorExpr * ctorExpr ) {1484 CandidateFinder finder( context, tenv );1485 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );1486 for ( CandidateRef & r : finder.candidates ) {1487 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } );1488 }1489 }1490 1491 void postvisit( const ast::RangeExpr * rangeExpr ) {1492 // resolve low and high, accept candidates where low and high types unify1493 CandidateFinder finder1( context, tenv );1494 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );1495 if ( finder1.candidates.empty() ) return;1496 1497 CandidateFinder finder2( context, tenv );1498 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );1499 if ( finder2.candidates.empty() ) return;1500 1501 reason.code = NoMatch;1502 1503 for ( const CandidateRef & r1 : finder1.candidates ) {1504 for ( const CandidateRef & r2 : finder2.candidates ) {1505 ast::TypeEnvironment env{ r1->env };1506 env.simpleCombine( r2->env );1507 ast::OpenVarSet open{ r1->open };1508 mergeOpenVars( open, r2->open );1509 ast::AssertionSet need;1510 mergeAssertionSet( need, r1->need );1511 mergeAssertionSet( need, r2->need );1512 ast::AssertionSet have;1513 1514 ast::ptr< ast::Type > common;1515 if (1516 unify(1517 r1->expr->result, r2->expr->result, env, need, have, open, symtab,1518 common )1519 ) {1520 // generate new expression1521 ast::RangeExpr * newExpr =1522 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };1523 newExpr->result = common ? common : r1->expr->result;1524 // add candidate1525 CandidateRef newCand = std::make_shared<Candidate>(1526 newExpr, std::move( env ), std::move( open ), std::move( need ),1527 r1->cost + r2->cost );1528 inferParameters( newCand, candidates );1529 }1530 }1531 }1532 }1533 1534 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {1535 std::vector< CandidateFinder > subCandidates =1536 selfFinder.findSubExprs( tupleExpr->exprs );1537 std::vector< CandidateList > possibilities;1538 combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) );1539 1540 for ( const CandidateList & subs : possibilities ) {1541 std::vector< ast::ptr< ast::Expr > > exprs;1542 exprs.reserve( subs.size() );1543 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); }1544 1545 ast::TypeEnvironment env;1546 ast::OpenVarSet open;1547 ast::AssertionSet need;1548 for ( const CandidateRef & sub : subs ) {1549 env.simpleCombine( sub->env );1550 mergeOpenVars( open, sub->open );1551 mergeAssertionSet( need, sub->need );1552 }1553 1554 addCandidate(1555 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },1556 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );1557 }1558 }1559 1560 void postvisit( const ast::TupleExpr * tupleExpr ) {1561 addCandidate( tupleExpr, tenv );1562 }1563 1564 void postvisit( const ast::TupleIndexExpr * tupleExpr ) {1565 addCandidate( tupleExpr, tenv );1566 }1567 1568 void postvisit( const ast::TupleAssignExpr * tupleExpr ) {1569 addCandidate( tupleExpr, tenv );1570 }1571 1572 void postvisit( const ast::UniqueExpr * unqExpr ) {1573 CandidateFinder finder( context, tenv );1574 finder.find( unqExpr->expr, ResolvMode::withAdjustment() );1575 for ( CandidateRef & r : finder.candidates ) {1576 // ensure that the the id is passed on so that the expressions are "linked"1577 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } );1578 }1579 }1580 1581 void postvisit( const ast::StmtExpr * stmtExpr ) {1582 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );1583 }1584 1585 void postvisit( const ast::UntypedInitExpr * initExpr ) {1586 // handle each option like a cast1587 CandidateList matches;1588 PRINT(1589 std::cerr << "untyped init expr: " << initExpr << std::endl;1590 )1591 // O(n^2) checks of d-types with e-types1592 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {1593 // calculate target type1594 const ast::Type * toType = resolveTypeof( initAlt.type, context );1595 toType = adjustExprType( toType, tenv, symtab );1596 // The call to find must occur inside this loop, otherwise polymorphic return1597 // types are not bound to the initialization type, since return type variables are1598 // only open for the duration of resolving the UntypedExpr.1599 CandidateFinder finder( context, tenv, toType );1600 finder.find( initExpr->expr, ResolvMode::withAdjustment() );1601 for ( CandidateRef & cand : finder.candidates ) {1602 if(reason.code == NotFound) reason.code = NoMatch;1603 1604 ast::TypeEnvironment env{ cand->env };1605 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;1606 ast::OpenVarSet open{ cand->open };1607 1608 PRINT(1609 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl;1610 )1611 1612 // It is possible that a cast can throw away some values in a multiply-valued1613 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of1614 // the subexpression results that are cast directly. The candidate is invalid1615 // if it has fewer results than there are types to cast to.1616 int discardedValues = cand->expr->result->size() - toType->size();1617 if ( discardedValues < 0 ) continue;1618 1619 // unification run for side-effects1620 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );1621 (void) canUnify;1622 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),1623 symtab, env );1624 PRINT(1625 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),1626 symtab, env );1627 std::cerr << "Considering initialization:";1628 std::cerr << std::endl << " FROM: " << cand->expr->result << std::endl;1629 std::cerr << std::endl << " TO: " << toType << std::endl;1630 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed");1631 std::cerr << std::endl << " Legacy cost " << legacyCost;1632 std::cerr << std::endl << " New cost " << thisCost;1633 std::cerr << std::endl;1634 )1635 if ( thisCost != Cost::infinity ) {1636 // count one safe conversion for each value that is thrown away1637 thisCost.incSafe( discardedValues );1638 CandidateRef newCand = std::make_shared<Candidate>(1639 new ast::InitExpr{1640 initExpr->location, restructureCast( cand->expr, toType ),1641 initAlt.designation },1642 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost );1643 inferParameters( newCand, matches );1644 }1645 }1646 1647 }1648 1649 // select first on argument cost, then conversion cost1650 CandidateList minArgCost = findMinCost( matches );1651 promoteCvtCost( minArgCost );1652 candidates = findMinCost( minArgCost );1653 }1654 1655 void postvisit( const ast::InitExpr * ) {1656 assertf( false, "CandidateFinder should never see a resolved InitExpr." );1657 }1658 1659 void postvisit( const ast::DeletedExpr * ) {1660 assertf( false, "CandidateFinder should never see a DeletedExpr." );1661 }1662 1663 void postvisit( const ast::GenericExpr * ) {1664 assertf( false, "_Generic is not yet supported." );1665 }1666 };1667 1668 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");1669 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given1670 /// return type. Skips ambiguous candidates.1671 1672 } // anonymous namespace1673 1674 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) {1675 struct PruneStruct {1676 CandidateRef candidate;1677 bool ambiguous;1678 1679 PruneStruct() = default;1680 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}1681 };1682 1683 // find lowest-cost candidate for each type1684 std::unordered_map< std::string, PruneStruct > selected;1685 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found1686 std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;});1687 for ( CandidateRef & candidate : candidates ) {1688 std::string mangleName;1689 {1690 ast::ptr< ast::Type > newType = candidate->expr->result;1691 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());1692 candidate->env.apply( newType );1693 mangleName = Mangle::mangle( newType );1694 }1695 1696 auto found = selected.find( mangleName );1697 if (found != selected.end() && found->second.candidate->cost < candidate->cost) {1698 PRINT(1699 std::cerr << "cost " << candidate->cost << " loses to "1700 << found->second.candidate->cost << std::endl;1701 )1702 continue;1703 }1704 1705 // xxx - when do satisfyAssertions produce more than 1 result?1706 // this should only happen when initial result type contains1707 // unbound type parameters, then it should never be pruned by1708 // the previous step, since renameTyVars guarantees the mangled name1709 // is unique.1710 CandidateList satisfied;1711 bool needRecomputeKey = false;1712 if (candidate->need.empty()) {1713 satisfied.emplace_back(candidate);1714 }1715 else {1716 satisfyAssertions(candidate, context.symtab, satisfied, errors);1717 needRecomputeKey = true;1718 }1719 1720 for (auto & newCand : satisfied) {1721 // recomputes type key, if satisfyAssertions changed it1722 if (needRecomputeKey)1723 {1724 ast::ptr< ast::Type > newType = newCand->expr->result;1725 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get());1726 newCand->env.apply( newType );1727 mangleName = Mangle::mangle( newType );1728 }1729 auto found = selected.find( mangleName );1730 if ( found != selected.end() ) {1731 if ( newCand->cost < found->second.candidate->cost ) {1732 PRINT(1733 std::cerr << "cost " << newCand->cost << " beats "1734 << found->second.candidate->cost << std::endl;1735 )1736 1737 found->second = PruneStruct{ newCand };1738 } else if ( newCand->cost == found->second.candidate->cost ) {1739 // if one of the candidates contains a deleted identifier, can pick the other,1740 // since deleted expressions should not be ambiguous if there is another option1741 // that is at least as good1742 if ( findDeletedExpr( newCand->expr ) ) {1743 // do nothing1744 PRINT( std::cerr << "candidate is deleted" << std::endl; )1745 } else if ( findDeletedExpr( found->second.candidate->expr ) ) {1746 PRINT( std::cerr << "current is deleted" << std::endl; )1747 found->second = PruneStruct{ newCand };1748 } else {1749 PRINT( std::cerr << "marking ambiguous" << std::endl; )1750 found->second.ambiguous = true;1751 }1752 } else {1753 // xxx - can satisfyAssertions increase the cost?1754 PRINT(1755 std::cerr << "cost " << newCand->cost << " loses to "1756 << found->second.candidate->cost << std::endl;1757 )1758 }1759 } else {1760 selected.emplace_hint( found, mangleName, newCand );1761 }1762 }1763 }1764 1765 // report unambiguous min-cost candidates1766 // CandidateList out;1767 for ( auto & target : selected ) {1768 if ( target.second.ambiguous ) continue;1769 1770 CandidateRef cand = target.second.candidate;1771 1772 ast::ptr< ast::Type > newResult = cand->expr->result;1773 cand->env.applyFree( newResult );1774 cand->expr = ast::mutate_field(1775 cand->expr.get(), &ast::Expr::result, std::move( newResult ) );1776 1777 out.emplace_back( cand );1778 }1779 // if everything is lost in satisfyAssertions, report the error1780 return !selected.empty();1781 }1782 1783 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {1784 // Find alternatives for expression1785 ast::Pass<Finder> finder{ *this };1786 expr->accept( finder );1787 1788 if ( mode.failFast && candidates.empty() ) {1789 switch(finder.core.reason.code) {1790 case Finder::NotFound:1791 { SemanticError( expr, "No alternatives for expression " ); break; }1792 case Finder::NoMatch:1793 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }1794 case Finder::ArgsToFew:1795 case Finder::ArgsToMany:1796 case Finder::RetsToFew:1797 case Finder::RetsToMany:1798 case Finder::NoReason:1799 default:1800 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }1801 }1802 }1803 1804 /*1805 if ( mode.satisfyAssns || mode.prune ) {1806 // trim candidates to just those where the assertions are satisfiable1807 // - necessary pre-requisite to pruning1808 CandidateList satisfied;1809 std::vector< std::string > errors;1810 for ( CandidateRef & candidate : candidates ) {1811 satisfyAssertions( candidate, localSyms, satisfied, errors );1812 }1813 1814 // fail early if none such1815 if ( mode.failFast && satisfied.empty() ) {1816 std::ostringstream stream;1817 stream << "No alternatives with satisfiable assertions for " << expr << "\n";1818 for ( const auto& err : errors ) {1819 stream << err;1820 }1821 SemanticError( expr->location, stream.str() );1822 }1823 1824 // reset candidates1825 candidates = move( satisfied );1826 }1827 */1828 1829 if ( mode.prune ) {1830 // trim candidates to single best one1831 PRINT(1832 std::cerr << "alternatives before prune:" << std::endl;1833 print( std::cerr, candidates );1834 )1835 1836 CandidateList pruned;1837 std::vector<std::string> errors;1838 bool found = pruneCandidates( candidates, pruned, errors );1839 1840 if ( mode.failFast && pruned.empty() ) {1841 std::ostringstream stream;1842 if (found) {1843 CandidateList winners = findMinCost( candidates );1844 stream << "Cannot choose between " << winners.size() << " alternatives for "1845 "expression\n";1846 ast::print( stream, expr );1847 stream << " Alternatives are:\n";1848 print( stream, winners, 1 );1849 SemanticError( expr->location, stream.str() );1850 }1851 else {1852 stream << "No alternatives with satisfiable assertions for " << expr << "\n";1853 for ( const auto& err : errors ) {1854 stream << err;1855 }1856 SemanticError( expr->location, stream.str() );1857 }1858 }1859 1860 auto oldsize = candidates.size();1861 candidates = std::move( pruned );1862 1863 PRINT(1864 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;1865 )1866 PRINT(1867 std::cerr << "there are " << candidates.size() << " alternatives after elimination"1868 << std::endl;1869 )1870 }1871 1872 // adjust types after pruning so that types substituted by pruneAlternatives are correctly1873 // adjusted1874 if ( mode.adjust ) {1875 for ( CandidateRef & r : candidates ) {1876 r->expr = ast::mutate_field(1877 r->expr.get(), &ast::Expr::result,1878 adjustExprType( r->expr->result, r->env, context.symtab ) );1879 }1880 }1881 1882 // Central location to handle gcc extension keyword, etc. for all expressions1883 for ( CandidateRef & r : candidates ) {1884 if ( r->expr->extension != expr->extension ) {1885 r->expr.get_and_mutate()->extension = expr->extension;1886 }1887 }1888 }1889 1890 std::vector< CandidateFinder > CandidateFinder::findSubExprs(1891 const std::vector< ast::ptr< ast::Expr > > & xs1892 ) {1893 std::vector< CandidateFinder > out;1894 1895 for ( const auto & x : xs ) {1896 out.emplace_back( context, env );1897 out.back().find( x, ResolvMode::withAdjustment() );1898 1899 PRINT(1900 std::cerr << "findSubExprs" << std::endl;1901 print( std::cerr, out.back().candidates );1902 )1903 }1904 1905 return out;1906 }1907 1908 1970 } // namespace ResolvExpr 1909 1971 -
src/ResolvExpr/CurrentObject.cc
ra50fdfb r6e1e2d0 9 9 // Author : Rob Schluntz 10 10 // Created On : Tue Jun 13 15:28:32 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 1 09:16:01 202213 // Update Count : 1 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 10 9:40:00 2023 13 // Update Count : 18 14 14 // 15 15 … … 593 593 594 594 namespace ast { 595 /// Iterates members of a type by initializer. 596 class MemberIterator { 597 public: 598 virtual ~MemberIterator() {} 599 600 /// Internal set position based on iterator ranges. 601 virtual void setPosition( 602 std::deque< ptr< Expr > >::const_iterator it, 603 std::deque< ptr< Expr > >::const_iterator end ) = 0; 604 605 /// Walks the current object using the given designators as a guide. 606 void setPosition( const std::deque< ptr< Expr > > & designators ) { 607 setPosition( designators.begin(), designators.end() ); 608 } 609 610 /// Retrieve the list of possible (Type,Designation) pairs for the 611 /// current position in the current object. 612 virtual std::deque< InitAlternative > operator* () const = 0; 613 614 /// True if the iterator is not currently at the end. 615 virtual operator bool() const = 0; 616 617 /// Moves the iterator by one member in the current object. 618 virtual MemberIterator & bigStep() = 0; 619 620 /// Moves the iterator by one member in the current subobject. 621 virtual MemberIterator & smallStep() = 0; 622 623 /// The type of the current object. 624 virtual const Type * getType() = 0; 625 626 /// The type of the current subobject. 627 virtual const Type * getNext() = 0; 628 629 /// Helper for operator*; aggregates must add designator to each init 630 /// alternative, but adding designators in operator* creates duplicates. 631 virtual std::deque< InitAlternative > first() const = 0; 632 }; 633 595 634 /// create a new MemberIterator that traverses a type correctly 596 635 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ); … … 632 671 }; 633 672 634 /// Iterates array types 635 class ArrayIterator final : public MemberIterator { 673 /// Iterates over an indexed type: 674 class IndexIterator : public MemberIterator { 675 protected: 636 676 CodeLocation location; 637 const ArrayType * array = nullptr;638 const Type * base = nullptr;639 677 size_t index = 0; 640 678 size_t size = 0; 641 std::unique_ptr< MemberIterator > memberIter; 642 643 void setSize( const Expr * expr ) { 644 auto res = eval( expr ); 645 if ( ! res.second ) { 646 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) ); 647 } 648 size = res.first; 649 } 650 651 public: 652 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : location( loc ), array( at ), base( at->base ) { 653 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 654 memberIter.reset( createMemberIterator( loc, base ) ); 655 if ( at->isVarLen ) { 656 SemanticError( location, at, "VLA initialization does not support @=: " ); 657 } 658 setSize( at->dimension ); 659 } 679 std::unique_ptr<MemberIterator> memberIter; 680 public: 681 IndexIterator( const CodeLocation & loc, size_t size ) : 682 location( loc ), size( size ) 683 {} 660 684 661 685 void setPosition( const Expr * expr ) { … … 666 690 auto arg = eval( expr ); 667 691 index = arg.first; 668 return;669 692 670 693 // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { … … 684 707 685 708 void setPosition( 686 std::deque< ptr< Expr >>::const_iterator begin,687 std::deque< ptr< Expr >>::const_iterator end709 std::deque<ast::ptr<ast::Expr>>::const_iterator begin, 710 std::deque<ast::ptr<ast::Expr>>::const_iterator end 688 711 ) override { 689 712 if ( begin == end ) return; … … 696 719 697 720 operator bool() const override { return index < size; } 721 }; 722 723 /// Iterates over the members of array types: 724 class ArrayIterator final : public IndexIterator { 725 const ArrayType * array = nullptr; 726 const Type * base = nullptr; 727 728 size_t getSize( const Expr * expr ) { 729 auto res = eval( expr ); 730 if ( !res.second ) { 731 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) ); 732 } 733 return res.first; 734 } 735 736 public: 737 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : 738 IndexIterator( loc, getSize( at->dimension) ), 739 array( at ), base( at->base ) { 740 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 741 memberIter.reset( createMemberIterator( loc, base ) ); 742 if ( at->isVarLen ) { 743 SemanticError( location, at, "VLA initialization does not support @=: " ); 744 } 745 } 698 746 699 747 ArrayIterator & bigStep() override { … … 834 882 835 883 const Type * getNext() final { 836 return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr; 884 bool hasMember = memberIter && *memberIter; 885 return hasMember ? memberIter->getType() : nullptr; 837 886 } 838 887 … … 898 947 }; 899 948 900 class TupleIterator final : public AggregateIterator { 901 public: 902 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 903 : AggregateIterator( 904 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 905 ) {} 906 907 operator bool() const override { 908 return curMember != members.end() || (memberIter && *memberIter); 949 /// Iterates across the positions in a tuple: 950 class TupleIterator final : public IndexIterator { 951 ast::TupleType const * const tuple; 952 953 const ast::Type * typeAtIndex() const { 954 assert( index < size ); 955 return tuple->types[ index ].get(); 956 } 957 958 public: 959 TupleIterator( const CodeLocation & loc, const TupleType * type ) 960 : IndexIterator( loc, type->size() ), tuple( type ) { 961 PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; ) 962 memberIter.reset( createMemberIterator( loc, typeAtIndex() ) ); 909 963 } 910 964 911 965 TupleIterator & bigStep() override { 912 PRINT( std::cerr << "bigStep in " << kind << std::endl; ) 913 atbegin = false; 914 memberIter = nullptr; 915 curType = nullptr; 916 while ( curMember != members.end() ) { 917 ++curMember; 918 if ( init() ) return *this; 919 } 966 ++index; 967 memberIter.reset( index < size ? 968 createMemberIterator( location, typeAtIndex() ) : nullptr ); 920 969 return *this; 970 } 971 972 TupleIterator & smallStep() override { 973 if ( memberIter ) { 974 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; ) 975 memberIter->smallStep(); 976 if ( !memberIter ) { 977 PRINT( std::cerr << "has valid member iter" << std::endl; ) 978 return *this; 979 } 980 } 981 return bigStep(); 982 } 983 984 const ast::Type * getType() override { 985 return tuple; 986 } 987 988 const ast::Type * getNext() override { 989 bool hasMember = memberIter && *memberIter; 990 return hasMember ? memberIter->getType() : nullptr; 991 } 992 993 std::deque< InitAlternative > first() const override { 994 PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; ) 995 if ( memberIter && *memberIter ) { 996 std::deque< InitAlternative > ret = memberIter->first(); 997 for ( InitAlternative & alt : ret ) { 998 alt.designation.get_and_mutate()->designators.emplace_front( 999 ConstantExpr::from_ulong( location, index ) ); 1000 } 1001 return ret; 1002 } 1003 return {}; 921 1004 } 922 1005 }; -
src/ResolvExpr/CurrentObject.h
ra50fdfb r6e1e2d0 9 9 // Author : Rob Schluntz 10 10 // Created On : Thu Jun 8 11:07:25 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:36:48 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 6 16:14:00 2023 13 // Update Count : 4 14 14 // 15 15 … … 65 65 66 66 /// Iterates members of a type by initializer 67 class MemberIterator { 68 public: 69 virtual ~MemberIterator() {} 70 71 /// Internal set position based on iterator ranges 72 virtual void setPosition( 73 std::deque< ptr< Expr > >::const_iterator it, 74 std::deque< ptr< Expr > >::const_iterator end ) = 0; 75 76 /// walks the current object using the given designators as a guide 77 void setPosition( const std::deque< ptr< Expr > > & designators ) { 78 setPosition( designators.begin(), designators.end() ); 79 } 80 81 /// retrieve the list of possible (Type,Designation) pairs for the current position in the 82 /// current object 83 virtual std::deque< InitAlternative > operator* () const = 0; 84 85 /// true if the iterator is not currently at the end 86 virtual operator bool() const = 0; 87 88 /// moves the iterator by one member in the current object 89 virtual MemberIterator & bigStep() = 0; 90 91 /// moves the iterator by one member in the current subobject 92 virtual MemberIterator & smallStep() = 0; 93 94 /// the type of the current object 95 virtual const Type * getType() = 0; 96 97 /// the type of the current subobject 98 virtual const Type * getNext() = 0; 99 100 /// helper for operator*; aggregates must add designator to each init alternative, but 101 /// adding designators in operator* creates duplicates 102 virtual std::deque< InitAlternative > first() const = 0; 103 }; 67 class MemberIterator; 104 68 105 69 /// Builds initializer lists in resolution -
src/ResolvExpr/ExplodedArg.hpp
ra50fdfb r6e1e2d0 35 35 ExplodedArg() : env(), cost( Cost::zero ), exprs() {} 36 36 ExplodedArg( const Candidate & arg, const ast::SymbolTable & symtab ); 37 37 38 38 ExplodedArg( ExplodedArg && ) = default; 39 39 ExplodedArg & operator= ( ExplodedArg && ) = default; -
src/SymTab/Autogen.cc
ra50fdfb r6e1e2d0 10 10 // Created On : Thu Mar 03 15:45:56 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 27 14:39:06 201813 // Update Count : 6 312 // Last Modified On : Fri Apr 14 15:03:00 2023 13 // Update Count : 64 14 14 // 15 15 … … 211 211 } 212 212 213 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {214 return obj && obj->name.empty() && obj->bitfieldWidth;215 }216 217 213 /// inserts a forward declaration for functionDecl into declsToAdd 218 214 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { … … 234 230 } 235 231 236 // shallow copy the pointer list for return237 std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {238 if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {239 return structInst->base->params;240 }241 if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {242 return unionInst->base->params;243 }244 return {};245 }246 247 232 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 248 233 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { … … 256 241 ftype->parameters.push_back( dstParam ); 257 242 return ftype; 258 }259 260 /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).261 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {262 std::vector<ast::ptr<ast::TypeDecl>> typeParams;263 if (maybePolymorphic) typeParams = getGenericParams(paramType);264 auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);265 return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc), {}, ast::Linkage::Cforall);266 243 } 267 244 -
src/SymTab/Autogen.h
ra50fdfb r6e1e2d0 9 9 // Author : Rob Schluntz 10 10 // Created On : Sun May 17 21:53:34 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Dec 13 16:38:06 201913 // Update Count : 1 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Apr 14 15:06:00 2023 13 // Update Count : 17 14 14 // 15 15 … … 45 45 /// returns true if obj's name is the empty string and it has a bitfield width 46 46 bool isUnnamedBitfield( ObjectDecl * obj ); 47 bool isUnnamedBitfield( const ast::ObjectDecl * obj );48 47 49 48 /// generate the type of an assignment function for paramType. … … 55 54 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true ); 56 55 57 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);58 59 56 /// generate the type of a copy constructor for paramType. 60 57 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic … … 67 64 template< typename OutputIterator > 68 65 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true ); 69 70 template< typename OutIter >71 ast::ptr< ast::Stmt > genCall(72 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,73 const CodeLocation & loc, const std::string & fname, OutIter && out,74 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );75 66 76 67 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. … … 121 112 122 113 *out++ = new ExprStmt( fExpr ); 123 124 srcParam.clearArrayIndices();125 126 return listInit;127 }128 129 /// inserts into out a generated call expression to function fname with arguments dstParam and130 /// srcParam. Should only be called with non-array types.131 /// optionally returns a statement which must be inserted prior to the containing loop, if132 /// there is one133 template< typename OutIter >134 ast::ptr< ast::Stmt > genScalarCall(135 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,136 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,137 const ast::Type * addCast = nullptr138 ) {139 bool isReferenceCtorDtor = false;140 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {141 // reference constructors are essentially application of the rebind operator.142 // apply & to both arguments, do not need a cast143 fname = "?=?";144 dstParam = new ast::AddressExpr{ dstParam };145 addCast = nullptr;146 isReferenceCtorDtor = true;147 }148 149 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of150 // "?=?", "?{}", or "^?{}"151 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };152 153 if ( addCast ) {154 // cast to T& with qualifiers removed, so that qualified objects can be constructed and155 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue156 // is considered a qualifier - for AddressExpr to resolve, its argument must have an157 // lvalue-qualified type, so remove all qualifiers except lvalue.158 // xxx -- old code actually removed lvalue too...159 ast::ptr< ast::Type > guard = addCast; // prevent castType from mutating addCast160 ast::ptr< ast::Type > castType = addCast;161 ast::remove_qualifiers(162 castType,163 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );164 dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };165 }166 fExpr->args.emplace_back( dstParam );167 168 ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );169 170 // fetch next set of arguments171 ++srcParam;172 173 // return if adding reference fails -- will happen on default ctor and dtor174 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;175 176 std::vector< ast::ptr< ast::Expr > > args = *srcParam;177 splice( fExpr->args, args );178 179 *out++ = new ast::ExprStmt{ loc, fExpr };180 114 181 115 srcParam.clearArrayIndices(); … … 248 182 } 249 183 250 /// Store in out a loop which calls fname on each element of the array with srcParam and251 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0252 template< typename OutIter >253 void genArrayCall(254 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,255 const CodeLocation & loc, const std::string & fname, OutIter && out,256 const ast::ArrayType * array, const ast::Type * addCast = nullptr,257 LoopDirection forward = LoopForward258 ) {259 static UniqueName indexName( "_index" );260 261 // for a flexible array member nothing is done -- user must define own assignment262 if ( ! array->dimension ) return;263 264 if ( addCast ) {265 // peel off array layer from cast266 addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;267 }268 269 ast::ptr< ast::Expr > begin, end;270 std::string cmp, update;271 272 if ( forward ) {273 // generate: for ( int i = 0; i < N; ++i )274 begin = ast::ConstantExpr::from_int( loc, 0 );275 end = array->dimension;276 cmp = "?<?";277 update = "++?";278 } else {279 // generate: for ( int i = N-1; i >= 0; --i )280 begin = ast::UntypedExpr::createCall( loc, "?-?",281 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );282 end = ast::ConstantExpr::from_int( loc, 0 );283 cmp = "?>=?";284 update = "--?";285 }286 287 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{288 loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },289 new ast::SingleInit{ loc, begin } };290 ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };291 292 ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(293 loc, cmp, { indexVar, end } );294 295 ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(296 loc, update, { indexVar } );297 298 ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(299 loc, "?[?]", { dstParam, indexVar } );300 301 // srcParam must keep track of the array indices to build the source parameter and/or302 // array list initializer303 srcParam.addArrayIndex( indexVar, array->dimension );304 305 // for stmt's body, eventually containing call306 ast::CompoundStmt * body = new ast::CompoundStmt{ loc };307 ast::ptr< ast::Stmt > listInit = genCall(308 srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,309 forward );310 311 // block containing the stmt and index variable312 ast::CompoundStmt * block = new ast::CompoundStmt{ loc };313 block->push_back( new ast::DeclStmt{ loc, index } );314 if ( listInit ) { block->push_back( listInit ); }315 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );316 317 *out++ = block;318 }319 320 184 template< typename OutputIterator > 321 185 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) { … … 325 189 } else { 326 190 return genScalarCall( srcParam, dstParam, fname, out, type, addCast ); 327 }328 }329 330 template< typename OutIter >331 ast::ptr< ast::Stmt > genCall(332 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,333 const CodeLocation & loc, const std::string & fname, OutIter && out,334 const ast::Type * type, const ast::Type * addCast, LoopDirection forward335 ) {336 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {337 genArrayCall(338 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,339 forward );340 return {};341 } else {342 return genScalarCall(343 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );344 191 } 345 192 } … … 379 226 } 380 227 381 static inline ast::ptr< ast::Stmt > genImplicitCall(382 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,383 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,384 LoopDirection forward = LoopForward385 ) {386 // unnamed bit fields are not copied as they cannot be accessed387 if ( isUnnamedBitfield( obj ) ) return {};388 389 ast::ptr< ast::Type > addCast;390 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {391 assert( dstParam->result );392 addCast = dstParam->result;393 }394 395 std::vector< ast::ptr< ast::Stmt > > stmts;396 genCall(397 srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );398 399 if ( stmts.empty() ) {400 return {};401 } else if ( stmts.size() == 1 ) {402 const ast::Stmt * callStmt = stmts.front();403 if ( addCast ) {404 // implicitly generated ctor/dtor calls should be wrapped so that later passes are405 // aware they were generated.406 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };407 }408 return callStmt;409 } else {410 assert( false );411 return {};412 }413 }414 228 } // namespace SymTab 415 229 -
src/SymTab/module.mk
ra50fdfb r6e1e2d0 20 20 SymTab/FixFunction.cc \ 21 21 SymTab/FixFunction.h \ 22 SymTab/GenImplicitCall.cpp \ 23 SymTab/GenImplicitCall.hpp \ 22 24 SymTab/Indexer.cc \ 23 25 SymTab/Indexer.h \ -
src/Validate/Autogen.cpp
ra50fdfb r6e1e2d0 39 39 #include "InitTweak/GenInit.h" // for fixReturnStatements 40 40 #include "InitTweak/InitTweak.h" // for isAssignment, isCopyConstructor 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 41 42 #include "SymTab/Mangler.h" // for Mangler 42 43 #include "CompilationState.h" … … 423 424 for ( unsigned int index = 0 ; index < fields ; ++index ) { 424 425 auto member = aggr->members[index].strict_as<ast::DeclWithType>(); 425 if ( SymTab::isUnnamedBitfield(426 if ( ast::isUnnamedBitfield( 426 427 dynamic_cast<const ast::ObjectDecl *>( member ) ) ) { 427 428 if ( index == fields - 1 ) { … … 599 600 // Not sure why it could be null. 600 601 // Don't make a function for a parameter that is an unnamed bitfield. 601 if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) {602 if ( nullptr == field || ast::isUnnamedBitfield( field ) ) { 602 603 continue; 603 604 // Matching Parameter: Initialize the field by copy. -
src/main.cc
ra50fdfb r6e1e2d0 9 9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thr Feb 16 10:08:00202313 // Update Count : 68 011 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 21:12:17 2023 13 // Update Count : 682 14 14 // 15 15 … … 32 32 33 33 #include "AST/Convert.hpp" 34 #include "AST/Util.hpp" // for checkInvariants 34 35 #include "CompilationState.h" 35 36 #include "../config.h" // for CFA_LIBDIR … … 102 103 } 103 104 104 #define PASS( name, pass ) \ 105 // Helpers for checkInvariant: 106 void checkInvariants( std::list< Declaration * > & ) {} 107 using ast::checkInvariants; 108 109 #define PASS( name, pass, unit, ... ) \ 105 110 if ( errorp ) { cerr << name << endl; } \ 106 111 NewPass(name); \ 107 112 Stats::Time::StartBlock(name); \ 108 pass; \ 109 Stats::Time::StopBlock(); 113 pass(unit,##__VA_ARGS__); \ 114 Stats::Time::StopBlock(); \ 115 if ( invariant ) { \ 116 checkInvariants(unit); \ 117 } 118 119 #define DUMP( cond, unit ) \ 120 if ( cond ) { \ 121 dump(unit); \ 122 return EXIT_SUCCESS; \ 123 } 110 124 111 125 static bool waiting_for_gdb = false; // flag to set cfa-cpp to wait for gdb on start … … 298 312 transUnit = buildUnit(); 299 313 300 if ( astp ) { 301 dump( std::move( transUnit ) ); 302 return EXIT_SUCCESS; 303 } // if 314 DUMP( astp, std::move( transUnit ) ); 304 315 305 316 Stats::Time::StopBlock(); … … 310 321 } 311 322 312 PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) ); 313 // Hoist Type Decls pulls some declarations out of contexts where 314 // locations are not tracked. Perhaps they should be, but for now 315 // the full fill solves it. 316 forceFillCodeLocations( transUnit ); 317 318 PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) ); 319 if ( exdeclp ) { 320 dump( std::move( transUnit ) ); 321 return EXIT_SUCCESS; 322 } 323 324 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) ); 325 PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) ); 326 PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) ); 327 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) ); 328 329 PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) ); 330 331 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) ); 332 PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) ); 333 PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) ); 334 PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) ); 335 PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) ); 336 PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) ); 337 PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) ); 338 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) ); 339 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) ); 340 PASS( "Implement Waituntil", Concurrency::generateWaitUntil( transUnit ) ); 341 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) ); 342 343 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) ); 344 345 PASS( "Implement Actors", Concurrency::implementActors( transUnit ) ); 346 PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors(transUnit) ); 347 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) ); 348 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) ); 349 PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) ); 350 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) ); 351 PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) ); 352 PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) ); 323 PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit ); 324 325 PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit ); 326 DUMP( exdeclp, std::move( transUnit ) ); 327 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit ); 328 PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit ); 329 PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit ); 330 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit ); 331 332 PASS( "Link Reference To Types", Validate::linkReferenceToTypes, transUnit ); 333 334 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit ); 335 PASS( "Hoist Struct", Validate::hoistStruct, transUnit ); 336 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit ); 337 PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit ); 338 PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit ); 339 PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit ); 340 PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit ); 341 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit ); 342 PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit ); 343 PASS( "Implement Waituntil", Concurrency::generateWaitUntil, transUnit ); 344 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit ); 345 346 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit ); 347 348 PASS( "Implement Actors", Concurrency::implementActors, transUnit ); 349 PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit ); 350 PASS( "Implement Mutex", Concurrency::implementMutex, transUnit ); 351 PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit ); 352 PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit ); 353 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit ); 354 PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit ); 355 PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit ); 353 356 354 357 if ( symtabp ) { … … 361 364 } // if 362 365 363 if ( validp ) { 364 dump( std::move( transUnit ) ); 365 return EXIT_SUCCESS; 366 } // if 367 368 PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) ); 369 PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) ); 370 PASS( "Fix Names", CodeGen::fixNames( transUnit ) ); 371 PASS( "Gen Init", InitTweak::genInit( transUnit ) ); 372 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) ); 366 DUMP( validp, std::move( transUnit ) ); 367 368 PASS( "Translate Throws", ControlStruct::translateThrows, transUnit ); 369 PASS( "Fix Labels", ControlStruct::fixLabels, transUnit ); 370 PASS( "Fix Names", CodeGen::fixNames, transUnit ); 371 PASS( "Gen Init", InitTweak::genInit, transUnit ); 372 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit ); 373 373 374 374 if ( libcfap ) { … … 382 382 } // if 383 383 384 if ( bresolvep ) { 385 dump( std::move( transUnit ) ); 386 return EXIT_SUCCESS; 387 } // if 384 DUMP( bresolvep, std::move( transUnit ) ); 388 385 389 386 if ( resolvprotop ) { … … 392 389 } // if 393 390 394 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 395 if ( exprp ) { 396 dump( std::move( transUnit ) ); 397 return EXIT_SUCCESS; 398 } // if 399 400 forceFillCodeLocations( transUnit ); 401 402 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary())); 391 PASS( "Resolve", ResolvExpr::resolve, transUnit ); 392 DUMP( exprp, std::move( transUnit ) ); 393 394 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); 403 395 404 396 // fix ObjectDecl - replaces ConstructorInit nodes 405 if ( ctorinitp ) { 406 dump( std::move( transUnit ) ); 407 return EXIT_SUCCESS; 408 } // if 397 DUMP( ctorinitp, std::move( transUnit ) ); 409 398 410 399 // Currently not working due to unresolved issues with UniqueExpr 411 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 reused412 413 PASS( "Translate Tries", ControlStruct::translateTries ( transUnit ));414 PASS( "Gen Waitfor", Concurrency::generateWaitFor ( transUnit ));400 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 401 402 PASS( "Translate Tries", ControlStruct::translateTries, transUnit ); 403 PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit ); 415 404 416 405 // Needs to happen before tuple types are expanded. 417 PASS( "Convert Specializations", GenPoly::convertSpecializations( transUnit ) ); 418 419 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) ); 420 421 if ( tuplep ) { 422 dump( std::move( transUnit ) ); 423 return EXIT_SUCCESS; 424 } // if 406 PASS( "Convert Specializations", GenPoly::convertSpecializations, transUnit ); 407 408 PASS( "Expand Tuples", Tuples::expandTuples, transUnit ); 409 DUMP( tuplep, std::move( transUnit ) ); 425 410 426 411 // Must come after Translate Tries. 427 PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) ); 428 429 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) ); 430 if ( genericsp ) { 431 dump( std::move( transUnit ) ); 432 return EXIT_SUCCESS; 433 } // if 434 435 PASS( "Convert L-Value", GenPoly::convertLvalue( transUnit ) ); 412 PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit ); 413 414 PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit ); 415 DUMP( genericsp, std::move( transUnit ) ); 416 417 PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit ); 436 418 437 419 translationUnit = convert( std::move( transUnit ) ); 438 420 439 if ( bboxp ) { 440 dump( translationUnit ); 441 return EXIT_SUCCESS; 442 } // if 443 PASS( "Box", GenPoly::box( translationUnit ) ); 444 445 PASS( "Link-Once", CodeGen::translateLinkOnce( translationUnit ) ); 421 DUMP( bboxp, translationUnit ); 422 PASS( "Box", GenPoly::box, translationUnit ); 423 424 PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit ); 446 425 447 426 // Code has been lowered to C, now we can start generation. 448 427 449 if ( bcodegenp ) { 450 dump( translationUnit ); 451 return EXIT_SUCCESS; 452 } // if 428 DUMP( bcodegenp, translationUnit ); 453 429 454 430 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 457 433 458 434 CodeTools::fillLocations( translationUnit ); 459 PASS( "Code Gen", CodeGen::generate ( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ));435 PASS( "Code Gen", CodeGen::generate, translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ); 460 436 461 437 CodeGen::FixMain::fix( translationUnit, *output, … … 505 481 506 482 507 static const char optstring[] = ":c:gh lLmNnpdP:S:twW:D:";483 static const char optstring[] = ":c:ghilLmNnpdP:S:twW:D:"; 508 484 509 485 enum { PreludeDir = 128 }; … … 512 488 { "gdb", no_argument, nullptr, 'g' }, 513 489 { "help", no_argument, nullptr, 'h' }, 490 { "invariant", no_argument, nullptr, 'i' }, 514 491 { "libcfa", no_argument, nullptr, 'l' }, 515 492 { "linemarks", no_argument, nullptr, 'L' }, 516 { "no-main", no_argument, 0, 'm' },493 { "no-main", no_argument, nullptr, 'm' }, 517 494 { "no-linemarks", no_argument, nullptr, 'N' }, 518 495 { "no-prelude", no_argument, nullptr, 'n' }, … … 533 510 "wait for gdb to attach", // -g 534 511 "print translator help message", // -h 512 "invariant checking during AST passes", // -i 535 513 "generate libcfa.c", // -l 536 514 "generate line marks", // -L … … 626 604 usage( argv ); // no return 627 605 break; 606 case 'i': // invariant checking 607 invariant = true; 608 break; 628 609 case 'l': // generate libcfa.c 629 610 libcfap = true; -
tests/.expect/PRNG.x64.txt
ra50fdfb r6e1e2d0 1 2 CFA xoshiro256pp 1 3 2 4 PRNG() PRNG(5) PRNG(0,5) … … 56 58 57 59 Sequential 58 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%60 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 59 61 60 62 Concurrent 61 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%62 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%63 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%64 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2%63 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 64 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 65 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 66 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0% 65 67 66 68 prng(t) prng(t,5) prng(t,0,5) -
tests/.expect/PRNG.x86.txt
ra50fdfb r6e1e2d0 1 2 CFA xoshiro128pp 1 3 2 4 PRNG() PRNG(5) PRNG(0,5) … … 56 58 57 59 Sequential 58 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%60 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 59 61 60 62 Concurrent 61 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%62 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%63 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%64 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2%63 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 64 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 65 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 66 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1% 65 67 66 68 prng(t) prng(t,5) prng(t,0,5) -
tests/Makefile.am
ra50fdfb r6e1e2d0 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Fri Feb 3 23:06:44202314 ## Update Count : 9 413 ## Last Modified On : Mon Apr 10 23:24:02 2023 14 ## Update Count : 96 15 15 ############################################################################### 16 16 … … 184 184 185 185 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator \ 186 init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment 186 init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment concurrent/waitfor/parse 187 187 $(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN) 188 188 $(CFACOMPILE_SYNTAX) -
tests/PRNG.cfa
ra50fdfb r6e1e2d0 8 8 // Created On : Wed Dec 29 09:38:12 2021 9 9 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Wed Dec 21 20:39:59 202211 // Update Count : 4 0610 // Last Modified On : Sun Apr 23 22:02:09 2023 11 // Update Count : 420 12 12 // 13 13 … … 15 15 #include <stdlib.hfa> // PRNG 16 16 #include <clock.hfa> 17 #include <thread.hfa>18 17 #include <limits.hfa> // MAX 19 18 #include <math.hfa> // sqrt 20 19 #include <malloc.h> // malloc_stats 21 20 #include <locale.h> // setlocale 21 #include <thread.hfa> 22 22 #include <mutex_stmt.hfa> 23 23 24 #ifdef __x86_64__ // 64-bit architecture 24 #define xstr(s) str(s) 25 #define str(s) #s 26 27 #if defined( __x86_64__ ) || defined( __aarch64__ ) // 64-bit architecture 25 28 #define PRNG PRNG64 26 29 #else // 32-bit architecture 27 30 #define PRNG PRNG32 28 31 #endif // __x86_64__ 32 33 //#define TIME 29 34 30 35 #ifdef TIME // use -O2 -nodebug … … 38 43 #endif // TIME 39 44 40 void avgstd( unsigned int buckets[] ) {41 unsigned int min = MAX, max = 0;45 static void avgstd( size_t trials, size_t buckets[] ) { 46 size_t min = MAX, max = 0; 42 47 double sum = 0.0, diff; 43 48 for ( i; BUCKETS ) { … … 54 59 } // for 55 60 double std = sqrt( sum / BUCKETS ); 56 mutex( sout ) sout | "trials" | TRIALS| "buckets" | BUCKETS61 mutex( sout ) sout | "trials" | trials | "buckets" | BUCKETS 57 62 | "min" | min | "max" | max 58 63 | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%"; … … 64 69 thread T1 {}; 65 70 void main( T1 & ) { 66 unsigned int * buckets = calloc( BUCKETS );// too big for task stack67 for ( TRIALS / 100 ) {71 size_t * buckets = calloc( BUCKETS ); // too big for task stack 72 for ( TRIALS / 50 ) { 68 73 buckets[rand() % BUCKETS] += 1; // concurrent 69 74 } // for 70 avgstd( buckets );75 avgstd( TRIALS / 50, buckets ); 71 76 free( buckets ); 72 77 } // main … … 76 81 PRNG prng; 77 82 if ( seed != 0 ) set_seed( prng, seed ); 78 unsigned int * buckets = calloc( BUCKETS );// too big for task stack83 size_t * buckets = calloc( BUCKETS ); // too big for task stack 79 84 for ( TRIALS ) { 80 85 buckets[prng( prng ) % BUCKETS] += 1; // concurrent 81 86 } // for 82 avgstd( buckets );87 avgstd( TRIALS, buckets ); 83 88 free( buckets ); 84 89 } // main … … 86 91 thread T3 {}; 87 92 void main( T3 & th ) { 88 unsigned int * buckets = calloc( BUCKETS );// too big for task stack89 for ( TRIALS ) {93 size_t * buckets = calloc( BUCKETS ); // too big for task stack 94 for ( TRIALS / 5 ) { 90 95 buckets[prng() % BUCKETS] += 1; // concurrent 91 96 } // for 92 avgstd( buckets );97 avgstd( TRIALS / 5, buckets ); 93 98 free( buckets ); 94 99 } // main … … 96 101 thread T4 {}; 97 102 void main( T4 & th ) { 98 unsigned int * buckets = calloc( BUCKETS );// too big for task stack103 size_t * buckets = calloc( BUCKETS ); // too big for task stack 99 104 for ( TRIALS ) { 100 buckets[prng( th ) % BUCKETS] += 1; // concurrent101 } // for 102 avgstd( buckets );105 buckets[prng( th ) % BUCKETS] += 1; // concurrent 106 } // for 107 avgstd( TRIALS, buckets ); 103 108 free( buckets ); 104 109 } // main … … 108 113 static void dummy( thread$ & th ) __attribute__(( noinline )); 109 114 static void dummy( thread$ & th ) { 110 unsigned int * buckets = (unsigned int *)calloc( BUCKETS, sizeof(unsigned int) ); // too big for task stack111 for ( unsigned int i = 0; i < TRIALS; i += 1 ) {115 size_t * buckets = (size_t *)calloc( BUCKETS, sizeof(size_t) ); // too big for task stack 116 for ( size_t i = 0; i < TRIALS; i += 1 ) { 112 117 buckets[prng( th ) % BUCKETS] += 1; // sequential 113 118 } // for 114 avgstd( buckets );119 avgstd( TRIALS, buckets ); 115 120 free( buckets ); 116 121 } // dummy … … 118 123 119 124 int main() { 120 // causes leaked storage message 121 // setlocale( LC_NUMERIC, getenv( "LANG" ) ); // print digit separator 125 // setlocale( LC_NUMERIC, getenv( "LANG" ) ); // causes leaked storage message 126 127 // only works on the current pthread thread 122 128 // locale_t loc = newlocale( LC_NUMERIC_MASK, getenv( "LANG" ), (locale_t)0p ); 123 129 // if ( loc == (locale_t)0p ) abort( "newlocale" ); … … 126 132 enum { TASKS = 4 }; 127 133 Time start; 134 128 135 #ifdef TIME // too slow for test and generates non-repeatable results 129 136 #if 1 130 unsigned int rseed; 137 sout | "glib rand" | nl | nl; 138 139 size_t rseed; 131 140 if ( seed != 0 ) rseed = seed; 132 141 else rseed = rdtscl(); … … 134 143 135 144 sout | sepDisable; 136 sout | wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" );145 sout | nl | wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" ); 137 146 for ( 20 ) { 138 147 sout | wd(26, rand()) | nonl; … … 146 155 STARTTIME; 147 156 { 148 unsigned int * buckets = calloc( BUCKETS );// too big for task stack149 for ( i; TRIALS / 10) {157 size_t * buckets = calloc( BUCKETS ); // too big for task stack 158 for ( i; TRIALS / 5 ) { 150 159 buckets[rand() % BUCKETS] += 1; // sequential 151 160 } // for 152 avgstd( buckets );161 avgstd( TRIALS / 5, buckets ); 153 162 free( buckets ); 154 163 } 155 ENDTIME( " x 10" );164 ENDTIME( " x 5 " ); 156 165 157 166 sout | nl | "Concurrent"; … … 163 172 } // wait for threads to complete 164 173 } 165 ENDTIME( " x 100 " );174 ENDTIME( " x 50 " ); 166 175 #endif // 0 167 176 #endif // TIME 177 178 sout | nl | "CFA " xstr(PRNG_NAME); 179 168 180 #if 1 169 181 PRNG prng; … … 184 196 STARTTIME; 185 197 { 186 unsigned int * buckets = calloc( BUCKETS );// too big for task stack198 size_t * buckets = calloc( BUCKETS ); // too big for task stack 187 199 for ( TRIALS ) { 188 200 buckets[prng( prng ) % BUCKETS] += 1; // sequential 189 201 } // for 190 avgstd( buckets );202 avgstd( TRIALS, buckets ); 191 203 free( buckets ); 192 204 } … … 219 231 STARTTIME; 220 232 { 221 unsigned int * buckets = calloc( BUCKETS );// too big for task stack222 for ( TRIALS ) {233 size_t * buckets = calloc( BUCKETS ); // too big for task stack 234 for ( TRIALS / 5 ) { 223 235 buckets[prng() % BUCKETS] += 1; 224 236 } // for 225 avgstd( buckets );237 avgstd( TRIALS / 5, buckets ); 226 238 free( buckets ); 227 239 } 228 ENDTIME( );240 ENDTIME( " x 5 " ); 229 241 230 242 sout | nl | "Concurrent"; … … 236 248 } // wait for threads to complete 237 249 } 238 ENDTIME( );250 ENDTIME( " x 5 " ); 239 251 #endif // 0 240 252 #if 1 -
tests/concurrent/waitfor/parse.cfa
ra50fdfb r6e1e2d0 1 // ----------------------------------------------------------------------------------------2 // ----------------------------------------------------------------------------------------1 // 2 // Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo 3 3 // 4 // DEPRECATED TEST 5 // DIFFERS BETWEEN DEBUG AND RELEASE 6 // 7 //---------------------------------------------------------------------------------------- 8 //---------------------------------------------------------------------------------------- 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // waitfor.c -- 8 // 9 // Author : Peter A. Buhr 10 // Created On : Wed Aug 30 17:53:29 2017 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 22:52:18 2023 13 // Update Count : 64 14 // 9 15 10 16 #include <monitor.hfa> … … 12 18 monitor M {}; 13 19 14 M a; 15 16 void f1( M & mutex a ); 17 void f2( M & mutex a ); 18 void f2( M & mutex a, M & mutex b ); 19 void f3( M & mutex a ); 20 void f3( M & mutex a, M & mutex b ); 21 void f3( M & mutex a, M & mutex b, M & mutex c ); 22 23 void foo() { 24 25 //--------------------------------------- 26 waitfor( f1 : a ) { 27 1; 28 } 29 30 //--------------------------------------- 31 waitfor( f1 : a ) { 32 2; 33 } 34 waitfor( f2 : a ) { 35 3; 36 } 37 38 //--------------------------------------- 39 when( 1 < 3 ) waitfor( f2 : a, a ) { 40 4; 41 } 42 or timeout( 100 ) { 43 5; 44 } 45 46 //--------------------------------------- 47 when( 2 < 3 ) waitfor( f3 : a ) { 48 5; 49 } 20 void notcalled( M & mutex m1, M & mutex m2 ) { 21 abort(); 22 } 23 void or( M & mutex m ) { 24 abort(); 25 } 26 void timeout( M & mutex m ) { 27 abort(); 28 } 29 30 void fred( M & mutex m, M & mutex or, M & mutex timeout ) { 31 // test waitfor and when 32 33 waitfor( notcalled : m, m ); 34 35 waitfor( notcalled : m, m ) { 36 } 37 38 waitfor( notcalled : m, m ) { 39 } 40 41 when( true ) waitfor( notcalled : m, m ); 42 43 when( true ) waitfor( notcalled : m, m ) { 44 } 45 46 waitfor( notcalled : m, m ); 47 or waitfor( notcalled : m, m ); 48 49 when( true ) waitfor( notcalled : m, m ); 50 or when( true ) waitfor( notcalled : m, m ); 51 52 waitfor( notcalled : m, m ) { 53 } or waitfor( notcalled : m, m ) { 54 } 55 56 waitfor( notcalled : m, m ) { 57 } or waitfor( notcalled : m, m ) { 58 } 59 60 when( true ) waitfor( notcalled : m, m ) { 61 } or when( true ) waitfor( notcalled : m, m ) { 62 } 63 64 waitfor( notcalled : m, m ); 65 or waitfor( notcalled : m, m ) { 66 } 67 68 when( true ) waitfor( notcalled : m, m ); 69 or when( true ) waitfor( notcalled : m, m ) { 70 } 71 72 waitfor( notcalled : m, m ) { 73 } or waitfor( notcalled : m, m ); 74 75 when( true ) waitfor( notcalled : m, m ) { 76 } or when( true ) waitfor( notcalled : m, m ); 77 78 // test when, waitfor and else 79 80 waitfor( notcalled : m, m ); 81 or else; 82 83 when( true ) waitfor( notcalled : m, m ); 84 or else; 85 86 when( true ) waitfor( notcalled : m, m ); 87 or else; 88 89 waitfor( notcalled : m, m ) { 90 } or else { 91 } 92 93 when( true ) waitfor( notcalled : m, m ) { 94 } or else { 95 } 96 97 waitfor( notcalled : m, m ); 50 98 or else { 51 6; 52 } 53 54 //--------------------------------------- 55 when( 3 < 3 ) waitfor( f3 : a, a ) { 56 7; 57 } 58 or when( 4 < 3 ) timeout( 101 ) { 59 8; 60 } 61 or when( 5 < 3 ) else { 62 9; 63 } 64 65 //--------------------------------------- 66 when( 6 < 3 ) waitfor( f3 : a, a, a ) { 67 10; 68 } 69 or when( 7 < 3 ) waitfor( f1 : a ) { 70 11; 71 } 99 } 100 101 when( true ) waitfor( notcalled : m, m ); 72 102 or else { 73 12; 74 } 75 76 //--------------------------------------- 77 when( 8 < 3 ) waitfor( f3 : a, a ) { 78 13; 79 } 80 or waitfor( f1 : a ) { 81 14; 82 } 83 or when( 9 < 3 ) timeout( 102 ) { 84 15; 85 } 86 87 //--------------------------------------- 88 when( 10 < 3 ) waitfor( f1 : a ) { 89 16; 90 } 91 or waitfor( f2 : a, a ) { 92 17; 93 } 94 or timeout( 103 ) { 95 18; 96 } 97 or when( 11 < 3 ) else { 98 19; 99 } 100 } 101 102 int main() {} 103 } 104 105 when( true ) waitfor( notcalled : m, m ); 106 or else { 107 } 108 109 waitfor( notcalled : m, m ) { 110 } or else; 111 112 when( true ) waitfor( notcalled : m, m ) { 113 } or else; 114 115 waitfor( notcalled : m, m ); 116 or when( true ) else; 117 118 when( true ) waitfor( notcalled : m, m ); 119 or when( true ) else; 120 121 when( true ) waitfor( notcalled : m, m ); 122 or when( true ) else; 123 124 waitfor( notcalled : m, m ) { 125 } or when( true ) else { 126 } 127 128 when( true ) waitfor( notcalled : m, m ) { 129 } or when( true ) else { 130 } 131 132 waitfor( notcalled : m, m ); 133 or when( true ) else { 134 } 135 136 when( true ) waitfor( notcalled : m, m ); 137 or when( true ) else { 138 } 139 140 when( true ) waitfor( notcalled : m, m ); 141 or when( true ) else { 142 } 143 144 waitfor( notcalled : m, m ) { 145 } or when( true ) else; 146 147 when( true ) waitfor( notcalled : m, m ) { 148 } or when( true ) else; 149 150 // test when, waitfor and timeout 151 152 waitfor( notcalled : m, m ); 153 or timeout( 3 ); 154 155 waitfor( notcalled : m, m ); 156 or timeout( 3 ); 157 158 when( true ) waitfor( notcalled : m, m ); 159 or timeout( 3 ); 160 161 waitfor( notcalled : m, m ) { 162 } or timeout( 3 ) { 163 } 164 165 when( true ) waitfor( notcalled : m, m ) { 166 } or timeout( 3 ) { 167 } 168 169 when( true ) waitfor( notcalled : m, m ) { 170 } or timeout( 3 ) { 171 } 172 173 when( true ) waitfor( notcalled : m, m ) { 174 } or when ( true ) timeout( 3 ) { 175 } 176 177 when( true ) waitfor( notcalled : m, m ) { 178 } or when ( true ) timeout( 3 ) { 179 } 180 181 waitfor( notcalled : m, m ); 182 or timeout( 3 ) { 183 } 184 185 when( true ) waitfor( notcalled : m, m ); 186 or timeout( 3 ) { 187 } 188 189 when( true ) waitfor( notcalled : m, m ); 190 or when( true ) timeout( 3 ) { 191 } 192 193 waitfor( notcalled : m, m ) { 194 } or timeout( 3 ); 195 196 when( true ) waitfor( notcalled : m, m ) { 197 } or timeout( 3 ); 198 199 when( true ) waitfor( notcalled : m, m ) { 200 } or when( true ) timeout( 3 ); 201 202 // test when, waitfor, timeout and else 203 204 waitfor( notcalled : m, m ) { 205 } or timeout( 3 ) { 206 } or when( true ) else {} 207 208 when( true ) waitfor( notcalled : m, m ) { 209 } or timeout( 3 ) { 210 } or when( true ) else {} 211 212 waitfor( notcalled : m, m ) { 213 } or timeout( 3 ) { 214 } or when( true ) else {} 215 216 waitfor( notcalled : m, m ) { 217 } or when( true ) timeout( 3 ) { 218 } or when( true ) else {} 219 220 when( true ) waitfor( notcalled : m, m ) { 221 } or timeout( 3 ) { 222 } or when( true ) else {} 223 224 waitfor( notcalled : m, m ) { 225 } or when( true ) timeout( 3 ) { 226 } or when( true ) else {} 227 228 when( true ) waitfor( notcalled : m, m ) { 229 } or when( true ) timeout( 3 ) { 230 } or when( true ) else {} 231 232 // test quasi-keywords "or" and "timeout" 233 234 int or = 0, timeout = 0; 235 waitfor( timeout : timeout ) timeout += 1; or timeout( timeout ); 236 waitfor( notcalled : or, or ) or += 1; or timeout( or ) 3; 237 when( or ) waitfor( or : m ) { 4; } or timeout( or ) or += 1; 238 when( timeout ) waitfor( notcalled : timeout, timeout ) or += 1; or else timeout += 1; 239 when( or + timeout ) waitfor( or : m ) 4; or when( or ) timeout( or ) 4; or when( or ) else timeout += 1; 240 when( 3 ) waitfor( or : or ) 3; or when( or ) waitfor( notcalled : or, or ) 4; or else 4; 241 when( timeout ) waitfor( or : timeout ) 3; or waitfor( notcalled : timeout, or ) 4; or when( or ) timeout( timeout ) 4; 242 when( 3 ) waitfor( or : timeout ) or += 1; 243 or waitfor( or : or ) timeout += 1; 244 or timeout( timeout ) or += 1; 245 or when( 3 ) else or += 1; 246 247 // test else selection 248 249 if ( or > timeout ) waitfor( or : or ) 3; 250 else waitfor( timeout : timeout ) 4; 251 } 252 253 //Dummy main 254 int main( int argc, char const * argv[] ) { 255 #pragma GCC warning "Compiled" // force non-empty .expect file, NO TABS!!! 256 } 257 258 // Local Variables: // 259 // tab-width: 4 // 260 // compile-command: "cfa waitfor.cfa" // 261 // End: // -
tests/pybin/settings.py
ra50fdfb r6e1e2d0 126 126 global archive 127 127 global install 128 global invariant 128 129 129 130 global continue_ … … 140 141 all_install = [Install(o) for o in list(dict.fromkeys(options.install))] 141 142 archive = os.path.abspath(os.path.join(original_path, options.archive_errors)) if options.archive_errors else None 143 invariant = options.invariant 142 144 continue_ = options.continue_ 143 145 dry_run = options.dry_run # must be called before tools.config_hash() -
tests/test.py
ra50fdfb r6e1e2d0 114 114 parser.add_argument('--install', help='Run all tests based on installed binaries or tree binaries', type=comma_separated(yes_no), default='no') 115 115 parser.add_argument('--continue', help='When multiple specifications are passed (debug/install/arch), sets whether or not to continue if the last specification failed', type=yes_no, default='yes', dest='continue_') 116 parser.add_argument('--invariant', help='Tell the compiler to check invariants while running.', action='store_true') 116 117 parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=180) 117 118 parser.add_argument('--global-timeout', help='Maximum cumulative duration in seconds after the ALL tests are considered to have timed out', type=int, default=7200) … … 172 173 test.prepare() 173 174 175 # extra flags for cfa to pass through make. 176 cfa_flags = 'CFAFLAGS=--invariant' if settings.invariant else None 177 174 178 # ---------- 175 179 # MAKE … … 177 181 # build, skipping to next test on error 178 182 with Timed() as comp_dur: 179 make_ret, _, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file)183 make_ret, _, _ = make(test.target(), flags=cfa_flags, output_file=subprocess.DEVNULL, error=out_file, error_file=err_file) 180 184 181 185 # ----------
Note:
See TracChangeset
for help on using the changeset viewer.