Changes in / [6e1e2d0:a50fdfb]
- Files:
-
- 1 added
- 7 deleted
- 86 edited
-
Jenkins/FullBuild (modified) (5 diffs)
-
Jenkinsfile (modified) (2 diffs)
-
doc/bibliography/pl.bib (modified) (1 diff)
-
doc/theses/colby_parsons_MMAth/.gitignore (modified) (1 diff)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_CFA.txt (modified) (15 diffs)
-
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_CFA.txt (modified) (15 diffs)
-
doc/theses/colby_parsons_MMAth/benchmarks/channels/plotData.py (modified) (1 diff)
-
doc/theses/colby_parsons_MMAth/code/swap_queues.cfa (modified) (3 diffs)
-
doc/theses/colby_parsons_MMAth/style/style.tex (modified) (1 diff)
-
doc/theses/colby_parsons_MMAth/text/actors.tex (modified) (15 diffs)
-
doc/theses/colby_parsons_MMAth/text/channels.tex (modified) (5 diffs)
-
doc/theses/colby_parsons_MMAth/text/mutex_stmt.tex (modified) (1 diff)
-
doc/theses/colby_parsons_MMAth/thesis.tex (modified) (1 diff)
-
doc/theses/colby_parsons_MMAth/version.sh (modified) (1 prop)
-
doc/theses/mike_brooks_MMath/benchmarks/list/Makefile (modified) (5 diffs)
-
doc/theses/mike_brooks_MMath/benchmarks/list/_classic.c (modified) (6 diffs)
-
doc/theses/mike_brooks_MMath/benchmarks/list/driver.c (modified) (9 diffs)
-
doc/theses/mike_brooks_MMath/benchmarks/list/observation.c (modified) (4 diffs)
-
doc/theses/mike_brooks_MMath/benchmarks/list/observation.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-allhead.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-inselem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-remelem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-allhead.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-inselem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-remelem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-allhead.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-inselem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-remelem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-allhead.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-inselem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-remelem.h (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/results-baseline.csv (modified) (1 diff)
-
doc/theses/mike_brooks_MMath/benchmarks/list/results-sizing.csv (deleted)
-
doc/theses/mike_brooks_MMath/pictures/lst-issues-direct.vsdx (modified) ( previous)
-
driver/cfa.cc (modified) (4 diffs)
-
src/AST/Attribute.hpp (modified) (1 diff)
-
src/AST/Convert.cpp (modified) (4 diffs)
-
src/AST/Decl.cpp (modified) (2 diffs)
-
src/AST/Decl.hpp (modified) (6 diffs)
-
src/AST/Expr.hpp (modified) (4 diffs)
-
src/AST/Init.hpp (modified) (1 diff)
-
src/AST/Inspect.cpp (modified) (2 diffs)
-
src/AST/Inspect.hpp (modified) (2 diffs)
-
src/AST/Pass.impl.hpp (modified) (1 diff)
-
src/AST/Print.cpp (modified) (1 diff)
-
src/AST/Stmt.hpp (modified) (6 diffs)
-
src/AST/SymbolTable.cpp (modified) (4 diffs)
-
src/AST/SymbolTable.hpp (modified) (1 diff)
-
src/AST/Type.cpp (modified) (2 diffs)
-
src/AST/Type.hpp (modified) (3 diffs)
-
src/Common/CodeLocationTools.cpp (modified) (2 diffs)
-
src/Common/Iterate.hpp (modified) (4 diffs)
-
src/CompilationState.cc (modified) (2 diffs)
-
src/CompilationState.h (modified) (2 diffs)
-
src/Concurrency/KeywordsNew.cpp (modified) (1 diff)
-
src/InitTweak/FixInitNew.cpp (modified) (9 diffs)
-
src/InitTweak/GenInit.cc (modified) (1 diff)
-
src/Parser/DeclarationNode.cc (modified) (7 diffs)
-
src/Parser/DeclarationNode.h (deleted)
-
src/Parser/ExpressionNode.cc (modified) (3 diffs)
-
src/Parser/ExpressionNode.h (deleted)
-
src/Parser/InitializerNode.cc (modified) (2 diffs)
-
src/Parser/InitializerNode.h (deleted)
-
src/Parser/ParseNode.h (modified) (3 diffs)
-
src/Parser/RunParser.cpp (modified) (1 diff)
-
src/Parser/StatementNode.cc (modified) (16 diffs)
-
src/Parser/StatementNode.h (deleted)
-
src/Parser/TypeData.cc (modified) (2 diffs)
-
src/Parser/TypeData.h (modified) (1 diff)
-
src/Parser/TypedefTable.cc (modified) (2 diffs)
-
src/Parser/TypedefTable.h (modified) (2 diffs)
-
src/Parser/lex.ll (modified) (1 diff)
-
src/Parser/module.mk (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (24 diffs)
-
src/Parser/parserutility.h (modified) (1 diff)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (3 diffs)
-
src/ResolvExpr/CurrentObject.cc (modified) (8 diffs)
-
src/ResolvExpr/CurrentObject.h (modified) (2 diffs)
-
src/ResolvExpr/ExplodedArg.hpp (modified) (1 diff)
-
src/SymTab/Autogen.cc (modified) (4 diffs)
-
src/SymTab/Autogen.h (modified) (8 diffs)
-
src/SymTab/GenImplicitCall.cpp (deleted)
-
src/SymTab/GenImplicitCall.hpp (deleted)
-
src/SymTab/module.mk (modified) (1 diff)
-
src/Validate/Autogen.cpp (modified) (3 diffs)
-
src/main.cc (modified) (13 diffs)
-
tests/.expect/PRNG.x64.txt (modified) (2 diffs)
-
tests/.expect/PRNG.x86.txt (modified) (2 diffs)
-
tests/Makefile.am (modified) (2 diffs)
-
tests/PRNG.cfa (modified) (17 diffs)
-
tests/concurrent/waitfor/parse.cfa (modified) (2 diffs)
-
tests/concurrent/waitfor/parse2.cfa (added)
-
tests/pybin/settings.py (modified) (2 diffs)
-
tests/test.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
Jenkins/FullBuild
r6e1e2d0 ra50fdfb 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 ) },23 22 gcc_10_x64_new: { trigger_build( 'gcc-10', 'x64', false ) }, 24 23 gcc_09_x64_new: { trigger_build( 'gcc-9', 'x64', false ) }, 25 24 gcc_08_x64_new: { trigger_build( 'gcc-8', 'x64', false ) }, 26 25 gcc_07_x64_new: { trigger_build( 'gcc-7', 'x64', false ) }, 27 //gcc_06_x64_new: { trigger_build( 'gcc-6', 'x64', false ) },26 gcc_06_x64_new: { trigger_build( 'gcc-6', 'x64', false ) }, 28 27 clang_x64_new: { trigger_build( 'clang', 'x64', true ) }, 29 28 ) … … 42 41 } 43 42 44 // If an exception is caught we need to change the status and remember to45 // attach the build log to the email43 //If an exception is caught we need to change the status and remember to 44 //attach the build log to the email 46 45 catch (Exception caughtError) { 47 46 echo('error caught') … … 74 73 // Run the build 75 74 // Don't propagate, it doesn't play nice with our email setup 76 def result = build job: 'Cforall/master', \75 def result = build job: 'Cforall/master', \ 77 76 parameters: [ \ 78 77 [$class: 'StringParameterValue', \ … … 84 83 [$class: 'BooleanParameterValue', \ 85 84 name: 'NewAST', \ 86 value: true], \85 value: true], \ 87 86 [$class: 'BooleanParameterValue', \ 88 87 name: 'RunAllTests', \ 89 value: true], \88 value: true], \ 90 89 [$class: 'BooleanParameterValue', \ 91 90 name: 'RunBenchmark', \ 92 value: true], \91 value: true], \ 93 92 [$class: 'BooleanParameterValue', \ 94 name: 'BuildDocumentation', \93 name: 'BuildDocumentation', \ 95 94 value: doc], \ 96 95 [$class: 'BooleanParameterValue', \ 97 96 name: 'Publish', \ 98 value: true], \97 value: true], \ 99 98 [$class: 'BooleanParameterValue', \ 100 99 name: 'Silent', \ 101 value: true], \102 ], \100 value: true], \ 101 ], \ 103 102 propagate: false 104 103 … … 112 111 113 112 def trigger_dist(String commitId, String buildNum) { 114 def result = build job: 'Cforall_Distribute_Ref', \113 def result = build job: 'Cforall_Distribute_Ref', \ 115 114 parameters: [ \ 116 115 string(name: 'GitRef', value: commitId), \ 117 string(name: 'Build' , value: buildNum) \118 ], \116 string(name: 'Build' , value: buildNum) \ 117 ], \ 119 118 propagate: false 120 119 -
Jenkinsfile
r6e1e2d0 ra50fdfb 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 clang', \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', \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\ngcc-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', \ 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',411 409 412 410 // It's unfortunate but it looks like we need to checkout the entire repo just to get -
doc/bibliography/pl.bib
r6e1e2d0 ra50fdfb 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 7464 7455 @article{Baker78, 7465 7456 keywords = {Algol display, FUNARG's, Lisp 1.5, deep binding, environment trees, multiprogramming, shallow binding}, -
doc/theses/colby_parsons_MMAth/.gitignore
r6e1e2d0 ra50fdfb 1 # Intermediate Results: 2 build/ 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 25 *.pdf 26 *.png 27 *.ps 28 figures/*.tex 3 29 4 # Final Files: 5 *.pdf 6 *.ps 7 8 # The Makefile here is not generated. 9 !Makefile 30 examples -
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/nasus_CFA.txt
r6e1e2d0 ra50fdfb 1 1 5 2 2 1 2 4 8 16 24 32 48 3 Longest-Victim No-Stealing Random3 CFA-LV CFA-NS CFA-R 4 4 executor 5 Longest-Victim:5 CFA-LV: 6 6 proc time (s) 7 7 1 29.22 … … 45 45 48 1.20 46 46 48 1.20 47 No-Stealing:47 CFA-NS: 48 48 proc time (s) 49 49 1 28.25 … … 87 87 48 1.18 88 88 48 1.16 89 Random:89 CFA-R: 90 90 proc time (s) 91 91 1 28.58 … … 131 131 132 132 matrix 133 Longest-Victim:133 CFA-LV: 134 134 proc time (s) 135 135 1 105.48 … … 173 173 48 2.75 174 174 48 2.96 175 No-Stealing:175 CFA-NS: 176 176 proc time (s) 177 177 1 106.01 … … 215 215 48 2.78 216 216 48 2.92 217 Random:217 CFA-R: 218 218 proc time (s) 219 219 1 105.91 … … 259 259 260 260 repeat 261 Longest-Victim:261 CFA-LV: 262 262 proc time (s) 263 263 1 1.17 … … 301 301 48 13.73 302 302 48 14.55 303 No-Stealing:303 CFA-NS: 304 304 proc time (s) 305 305 1 1.15 … … 343 343 48 13.03 344 344 48 12.83 345 Random:345 CFA-R: 346 346 proc time (s) 347 347 1 1.15 … … 387 387 388 388 balance_one 389 Longest-Victim:389 CFA-LV: 390 390 proc time (s) 391 391 1 20.06 … … 429 429 48 1.11 430 430 48 1.12 431 No-Stealing:431 CFA-NS: 432 432 proc time (s) 433 433 1 20.13 … … 471 471 48 19.95 472 472 48 20.00 473 Random:473 CFA-R: 474 474 proc time (s) 475 475 1 19.92 … … 515 515 516 516 balance_multi 517 Longest-Victim:517 CFA-LV: 518 518 proc time (s) 519 519 1 8.17 … … 557 557 48 5.75 558 558 48 5.68 559 No-Stealing:559 CFA-NS: 560 560 proc time (s) 561 561 1 8.10 … … 599 599 48 9.28 600 600 48 9.26 601 Random:601 CFA-R: 602 602 proc time (s) 603 603 1 8.08 -
doc/theses/colby_parsons_MMAth/benchmarks/actors/data/pyke_CFA.txt
r6e1e2d0 ra50fdfb 1 1 5 2 2 1 2 4 8 16 24 32 48 3 Longest-Victim No-Stealing Random3 CFA-LV CFA-NS CFA-R 4 4 executor 5 Longest-Victim:5 CFA-LV: 6 6 proc time (s) 7 7 1 29.04 … … 45 45 48 2.58 46 46 48 2.55 47 No-Stealing:47 CFA-NS: 48 48 proc time (s) 49 49 1 28.15 … … 87 87 48 2.59 88 88 48 2.60 89 Random:89 CFA-R: 90 90 proc time (s) 91 91 1 29.06 … … 131 131 132 132 matrix 133 Longest-Victim:133 CFA-LV: 134 134 proc time (s) 135 135 1 127.44 … … 173 173 48 6.83 174 174 48 6.81 175 No-Stealing:175 CFA-NS: 176 176 proc time (s) 177 177 1 127.64 … … 215 215 48 6.77 216 216 48 6.74 217 Random:217 CFA-R: 218 218 proc time (s) 219 219 1 127.26 … … 259 259 260 260 repeat 261 Longest-Victim:261 CFA-LV: 262 262 proc time (s) 263 263 1 1.16 … … 301 301 48 19.75 302 302 48 19.71 303 No-Stealing:303 CFA-NS: 304 304 proc time (s) 305 305 1 1.18 … … 343 343 48 13.88 344 344 48 13.71 345 Random:345 CFA-R: 346 346 proc time (s) 347 347 1 1.18 … … 387 387 388 388 balance_one 389 Longest-Victim:389 CFA-LV: 390 390 proc time (s) 391 391 1 19.46 … … 429 429 48 2.12 430 430 48 2.17 431 No-Stealing:431 CFA-NS: 432 432 proc time (s) 433 433 1 21.00 … … 471 471 48 47.50 472 472 48 47.72 473 Random:473 CFA-R: 474 474 proc time (s) 475 475 1 20.81 … … 515 515 516 516 balance_multi 517 Longest-Victim:517 CFA-LV: 518 518 proc time (s) 519 519 1 7.94 … … 557 557 48 14.38 558 558 48 14.50 559 No-Stealing:559 CFA-NS: 560 560 proc time (s) 561 561 1 8.48 … … 599 599 48 21.50 600 600 48 21.15 601 Random:601 CFA-R: 602 602 proc time (s) 603 603 1 8.49 -
doc/theses/colby_parsons_MMAth/benchmarks/channels/plotData.py
r6e1e2d0 ra50fdfb 70 70 if currBench == Bench.Unset: 71 71 if line == "contend:": 72 name = "C hannel Contention"72 name = "Contend" 73 73 currBench = Bench.Contend 74 74 elif line == "zero:": -
doc/theses/colby_parsons_MMAth/code/swap_queues.cfa
r6e1e2d0 ra50fdfb 1 // sequential equivalent swap 2 void swap( uint victim_idx, uint my_idx ) { 3 // Step 0: 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) { 4 6 work_queue * my_queue = request_queues[my_idx]; 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; 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; 12 26 } 13 27 … … 21 35 22 36 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 queues25 37 work_queue * my_queue = request_queues[my_idx]; 26 38 work_queue * vic_queue = request_queues[victim_idx]; 27 39 28 // Step 1:29 40 // If either queue is 0p then they are in the process of being stolen 30 41 // 0p is CForAll's equivalent of C++'s nullptr 31 if ( vic_queue == 0p ) return false;42 if ( vic_queue == 0p || my_queue == 0p ) return false; 32 43 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 44 // Try to set our queue ptr to be 0p. 45 // If this CAS fails someone moved our queue so return false 36 46 if ( !CAS( &request_queues[my_idx], &my_queue, 0p ) ) 37 47 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 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 42 51 if ( !CAS( &request_queues[victim_idx], &vic_queue, my_queue ) ) { 43 52 request_queues[my_idx] = my_queue; // reset queue ptr back to prev val … … 45 54 } 46 55 47 // Step 4:48 56 // Successfully swapped. 49 // Thief's ptr is 0p so no one will touch it 50 // Write back without CAS is safe 57 // Our queue is 0p so no one will touch it so write back without CAS is safe 51 58 request_queues[my_idx] = vic_queue; 52 59 return true; -
doc/theses/colby_parsons_MMAth/style/style.tex
r6e1e2d0 ra50fdfb 3 3 \lstset{language=CFA} % default language 4 4 5 \newcommand{\newtermFont}{\emph}6 \newcommand{\Newterm}[1]{\newtermFont{#1}}7 8 5 \newcommand{\code}[1]{\lstinline[language=CFA]{#1}} 9 6 \newcommand{\uC}{$\mu$\CC} 10 \newcommand{\PAB}[1]{{\color{red}PAB: #1}}11 7 12 \newsavebox{\myboxA} % used with subfigure13 \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
r6e1e2d0 ra50fdfb 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 ((actor &)this){}; // Call to actor ctor95 ((actor &)this){}; // Call to actor ctor 96 96 } 97 97 98 98 struct derived_msg { 99 inline message;// Plan-9 C nominal inheritance100 char word[12];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 ((message &) this){ Nodelete }; // Passing allocation to ctor104 strcpy(this.word, new_word);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 printf("The message contained the string: %s\n", msg.word);109 return Finished; // Return finished since actor is done108 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 start_actor_system(); // Sets up executor114 derived_actor my_actor;115 derived_msg my_msg{ "Hello World" }; // Constructor call116 my_actor << my_msg; // Send message via left shift operator117 stop_actor_system(); // Waits until actors are finished118 return 0;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 executes its behaviour that is associated with that message type.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 The goal of the \CFA actor work stealing mechanism is to have a zero-victim-cost stealing mechanism.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 // 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;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 if ( *ptr != *old )392 return false;393 *ptr = new;394 return true;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 // Step 0:399 // request_queues is the shared array of all sharded queues400 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 stolen405 // 0p is CForAll's equivalent of C++'s nullptr406 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 false411 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 false417 if ( !CAS( &request_queues[victim_idx], &vic_queue, my_queue ) ) {418 request_queues[my_idx] = my_queue; // reset queue ptr back to prev val419 return false;420 }421 422 // Step 4:423 // Successfully swapped.424 // Thief's ptr is 0p so no one will touch it425 // Write back without CAS is safe426 request_queues[my_idx] = vic_queue;427 return true;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 & \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}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 & \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}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, Akka and ProtoActor, slow down by a more significant margin than the \uC and \CFA.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 \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).} 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).} 778 786 \end{figure} 779 787 … … 809 817 810 818 \begin{figure} 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).} 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).} 821 833 \end{figure} 822 834 … … 828 840 829 841 \begin{figure} 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).} 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).} 840 854 \end{figure} 841 855 … … 843 857 844 858 \begin{figure} 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).} 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).} 855 871 \end{figure} 856 872 … … 865 881 866 882 \begin{figure} 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).} 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).} 877 895 \end{figure} 878 896 … … 895 913 896 914 \begin{table}[t] 897 \centering898 \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}915 \centering 916 \setlength{\extrarowheight}{2pt} 917 \setlength{\tabcolsep}{5pt} 918 919 \caption{Executor Program Memory High Watermark} 920 \label{t:ExecutorMemory} 921 \begin{tabular}{*{5}{r|}r} 922 & \multicolumn{1}{c|}{\CFA} & \multicolumn{1}{c|}{CAF} & \multicolumn{1}{c|}{Akka} & \multicolumn{1}{c|}{\uC} & \multicolumn{1}{c@{}}{ProtoActor} \\ 923 \hline 924 AMD & \input{data/pykeExecutorMem} \\ 925 \hline 926 Intel & \input{data/nasusExecutorMem} 927 \end{tabular} 910 928 \end{table} 911 929 … … 933 951 934 952 \begin{figure} 935 \centering936 \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: % 953 \centering 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} -
doc/theses/colby_parsons_MMAth/text/channels.tex
r6e1e2d0 ra50fdfb 5 5 % ====================================================================== 6 6 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 ... 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. 16 11 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.19 12 20 13 \section{Producer-Consumer Problem} 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. 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. 27 20 Additionally, a consumer can only remove from a non-empty buffer and a producer can only insert into a non-full buffer. 28 21 29 22 \section{First-Come First-Served} 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. 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. 36 29 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. 37 30 38 31 \section{Channel 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. 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. 42 35 As such the research contributions added by \CFA's channel implementation lie in the realm of safety and productivity features. 43 36 44 37 \section{Safety and Productivity} 45 Channels in \CFA come with safety and productivity features to aid users. 38 Channels in \CFA come with safety and productivity features to aid users. 46 39 The features include the following. 47 40 48 41 \begin{itemize} 49 \item Toggle-able statistic collection on channel beh aviour that counts channel operations, and the number of the operations that block.42 \item Toggle-able statistic collection on channel behvaiour that counts channel operations, and the number of the operations that block. 50 43 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. 51 \item Deadlock detection on deallocation of the channel. 44 \item Deadlock detection on deallocation of the channel. 52 45 If any threads are blocked inside the channel when it terminates it is detected and informs the user, as this would cause a deadlock. 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 rea cquire mutual exclusion for each element sent.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 reaquire mutual exclusion for each element sent. 56 49 \end{itemize} 57 50 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. 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. 65 58 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. 66 59 67 60 % C_TODO: add reference to select chapter, add citation to go channels info 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. 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. 79 72 Note that panics in Go can be caught, but it is not considered an idiomatic way to write Go programs. 80 73 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. 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. 86 79 Due to Go's asymmetric approach to channel shutdown, separate synchronization between producers and consumers of a channel has to occur during shutdown. 87 80 … … 89 82 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. 90 83 Resumption exceptions are a style of exception that when caught run the corresponding catch block in the same way that termination exceptions do. 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. 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. 96 89 This mechanism can be used to create a flexible and robust termination system for channels. 97 90 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. 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. 112 105 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. 113 106 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 exa mples 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. 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 exaples 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. 125 118 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. 126 119 127 \begin{cfa}[ caption={\CFA channel barrier termination},label={l:cfa_chan_bar}]120 \begin{cfa}[tabsize=3,caption={\CFA channel barrier termination},label={l:cfa_chan_bar}] 128 121 struct barrier { 129 channel( int ) barWait;130 channel( int ) entryWait;131 int size;122 channel( int ) barWait; 123 channel( int ) entryWait; 124 int size; 132 125 } 133 126 void ?{}(barrier & this, int size) with(this) { 134 barWait{size};135 entryWait{size};136 this.size = size;137 for ( j; size )138 insert( *entryWait, j );127 barWait{size}; 128 entryWait{size}; 129 this.size = size; 130 for ( j; size ) 131 insert( *entryWait, j ); 139 132 } 140 133 141 134 void flush(barrier & this) with(this) { 142 close(barWait);143 close(entryWait);135 close(barWait); 136 close(entryWait); 144 137 } 145 138 void wait(barrier & this) with(this) { 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 out155 if ( size == 1 || ticket == size - 2 ) {156 for ( j; size )157 insert( *entryWait, j );158 }139 int ticket = remove( *entryWait ); 140 if ( ticket == size - 1 ) { 141 for ( j; size - 1 ) 142 insert( *barWait, j ); 143 return; 144 } 145 ticket = remove( *barWait ); 146 147 // last one out 148 if ( size == 1 || ticket == size - 2 ) { 149 for ( j; size ) 150 insert( *entryWait, j ); 151 } 159 152 } 160 153 barrier b{Tasks}; … … 162 155 // thread main 163 156 void main(Task & this) { 164 try {165 for ( ;; ) {166 wait( b );167 }168 } catch ( channel_closed * e ) {}157 try { 158 for ( ;; ) { 159 wait( b ); 160 } 161 } catch ( channel_closed * e ) {} 169 162 } 170 163 171 164 int main() { 172 {173 Task t[Tasks];174 175 sleep(10`s);176 flush( b );177 } // wait for tasks to terminate178 return 0;165 { 166 Task t[Tasks]; 167 168 sleep(10`s); 169 flush( b ); 170 } // wait for tasks to terminate 171 return 0; 179 172 } 180 173 \end{cfa} 181 174 182 \begin{cfa}[ caption={Go channel barrier termination},label={l:go_chan_bar}]175 \begin{cfa}[tabsize=3,caption={Go channel barrier termination},label={l:go_chan_bar}] 183 176 184 177 struct barrier { 185 channel( int ) barWait;186 channel( int ) entryWait;187 int size;178 channel( int ) barWait; 179 channel( int ) entryWait; 180 int size; 188 181 } 189 182 void ?{}(barrier & this, int size) with(this) { 190 barWait{size + 1};191 entryWait{size + 1};192 this.size = size;193 for ( j; size )194 insert( *entryWait, j );183 barWait{size + 1}; 184 entryWait{size + 1}; 185 this.size = size; 186 for ( j; size ) 187 insert( *entryWait, j ); 195 188 } 196 189 197 190 void flush(barrier & this) with(this) { 198 insert( *entryWait, -1 );199 insert( *barWait, -1 );191 insert( *entryWait, -1 ); 192 insert( *barWait, -1 ); 200 193 } 201 194 void wait(barrier & this) with(this) { 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 out219 if ( size == 1 || ticket == size - 2 ) {220 for ( j; size )221 insert( *entryWait, j );222 }195 int ticket = remove( *entryWait ); 196 if ( ticket == -1 ) { 197 insert( *entryWait, -1 ); 198 return; 199 } 200 if ( ticket == size - 1 ) { 201 for ( j; size - 1 ) 202 insert( *barWait, j ); 203 return; 204 } 205 ticket = remove( *barWait ); 206 if ( ticket == -1 ) { 207 insert( *barWait, -1 ); 208 return; 209 } 210 211 // last one out 212 if ( size == 1 || ticket == size - 2 ) { 213 for ( j; size ) 214 insert( *entryWait, j ); 215 } 223 216 } 224 217 barrier b; … … 227 220 // thread main 228 221 void main(Task & this) { 229 for ( ;; ) {230 if ( done ) break;231 wait( b );232 }222 for ( ;; ) { 223 if ( done ) break; 224 wait( b ); 225 } 233 226 } 234 227 235 228 int main() { 236 {237 Task t[Tasks];238 239 sleep(10`s);240 done = true;241 242 flush( b );243 } // wait for tasks to terminate244 return 0;229 { 230 Task t[Tasks]; 231 232 sleep(10`s); 233 done = true; 234 235 flush( b ); 236 } // wait for tasks to terminate 237 return 0; 245 238 } 246 239 \end{cfa} 247 240 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. 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. 251 244 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. 252 245 253 \begin{cfa}[ caption={\CFA channel resumption usage},label={l:cfa_resume}]246 \begin{cfa}[tabsize=3,caption={\CFA channel resumption usage},label={l:cfa_resume}] 254 247 channel( int ) chan{ 128 }; 255 248 256 249 // Consumer thread main 257 250 void main(Consumer & this) { 258 size_t runs = 0;259 try {260 for ( ;; ) {261 remove( chan );262 }263 } catchResume ( channel_closed * e ) {}264 catch ( channel_closed * e ) {} 251 size_t runs = 0; 252 try { 253 for ( ;; ) { 254 remove( chan ); 255 } 256 } catchResume ( channel_closed * e ) {} 257 catch ( channel_closed * e ) {} 265 258 } 266 259 267 260 // Producer thread main 268 261 void main(Producer & this) { 269 int j = 0;270 try {271 for ( ;;j++ ) {272 insert( chan, j );273 }274 } catch ( channel_closed * e ) {} 262 int j = 0; 263 try { 264 for ( ;;j++ ) { 265 insert( chan, j ); 266 } 267 } catch ( channel_closed * e ) {} 275 268 } 276 269 277 270 int main( int argc, char * argv[] ) { 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;271 { 272 Consumers c[4]; 273 Producer p[4]; 274 275 sleep(10`s); 276 277 for ( i; Channels ) 278 close( channels[i] ); 279 } 280 return 0; 288 281 } 289 282 \end{cfa} … … 291 284 \section{Performance} 292 285 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 through put 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. 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 throughtput 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. 300 293 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. 301 294 302 295 303 296 \begin{figure} 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} 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} 315 310 \end{figure} 316 317 % Local Variables: %318 % tab-width: 4 %319 % End: % -
doc/theses/colby_parsons_MMAth/text/mutex_stmt.tex
r6e1e2d0 ra50fdfb 5 5 % ====================================================================== 6 6 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)}. 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}. 12 13 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. 14 \begin{cfa}[tabsize=3,caption={\CFA mutex statement usage},label={l:cfa_mutex_ex}] 15 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 21 22 \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 23 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. 24 \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}. 31 33 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}] 172 owner_lock lock1, lock2, lock3; 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 } 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 181 39 } 182 40 \end{cfa} 183 41 184 \section{Other Languages} 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}. 42 \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. 191 50 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}$ 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!"; 206 63 \end{cfa} 207 64 208 \section{\CFA implementation} 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}}. 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. 227 71 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}] 72 \begin{cfa}[caption={\CC scoped\_lock deadlock avoidance algorithm},label={l:cc_deadlock_avoid}] 277 73 int first = 0; // first lock to attempt to lock 278 74 do { 279 // locks is the array of locks to acquire280 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 }75 // locks is the array of locks to acquire 76 locks[first].lock(); // lock first lock 77 for (int i = 1; i < Num_Locks; ++i) { // iterate over rest of locks 78 const int idx = (first + i) % Num_Locks; 79 if (!locks[idx].try_lock()) { // try lock each one 80 for (int j = i; j != 0; --j) // release all locks 81 locks[(first + j - 1) % Num_Locks].unlock(); 82 first = idx; // rotate which lock to acquire first 83 break; 84 } 85 } 290 86 // if first lock is still held then all have been acquired 291 } while ( ! locks[first].owns_lock() ); $\C{// is first lock held?}$87 } while (!locks[first].owns_lock()); // is first lock held? 292 88 \end{cfa} 293 89 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@. 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. 303 98 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. 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. 310 107 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} 108 \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} 326 120 327 $\textbf{thread\(_2\)}$ 328 mutex( L1, L2 ) { 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} 329 131 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. 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} 144 \end{figure} 338 145 339 146 \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. 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. 352 155 The median is calculated and is plotted alongside the 95\% confidence intervals for each point. 353 156 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. 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. 387 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. 388 389 \begin{figure}390 \centering391 \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}415 \end{figure}416 417 % Local Variables: %418 % tab-width: 4 %419 % End: % -
doc/theses/colby_parsons_MMAth/thesis.tex
r6e1e2d0 ra50fdfb 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} 86 87 \usepackage{fullpage,times,comment} 87 88 \usepackage{textcomp} 88 89 \usepackage{graphicx} 89 90 \usepackage{tabularx} 90 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt,font=normalsize]{subfig}91 \renewcommand\thesubfigure{(\alph{subfigure})}92 91 \input{style} 93 92 -
doc/theses/colby_parsons_MMAth/version.sh
-
Property mode
changed from
100644to100755
-
Property mode
changed from
-
doc/theses/mike_brooks_MMath/benchmarks/list/Makefile
r6e1e2d0 ra50fdfb 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 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 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 11 9 12 10 CFA = cfa … … 14 12 UXX = ~/u++/u++-7.0.0/bin/u++ 15 13 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 14 MODE = performance 15 RUNARGS= 22 16 23 17 ifeq "$(MODE)" "performance" 24 PERFFLAGS_CFA = - DNDEBUG -O3 -nodebug18 PERFFLAGS_CFA = -nodebug -O3 25 19 PERFFLAGS_CC = -DNDEBUG -O3 26 20 else ifeq "$(MODE)" "correctness" 27 PERFFLAGS_CFA = - O0 -g -debug28 PERFFLAGS_CC = -O0 -g21 PERFFLAGS_CFA = -debug -O0 -g 22 PERFFLAGS_CC = -O0 -g 29 23 else 30 24 $(error Bad MODE ($(MODE)); should be performance or correctness) … … 32 26 33 27 PERFFLAGS_CXX = $(PERFFLAGS_CC) 34 PERFFLAGS_UXX = $(PERFFLAGS_CFA) 35 36 CFLAGS=$(PERFFLAGS_CC) $(EXTRA_COMP_FLAGS) 28 PERFFLAGS_UXX = $(PERFFLAGS_CC) 37 29 38 30 SHELL = /usr/bin/bash … … 109 101 perfexp--% driver--%.o : COMPILER=NO-COMPILER-FOR-$(FX_COARSE) 110 102 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-clean113 # Whatever you -include gets called as a target first.114 # One such example is driver--upp-upp--stack-insfirst-allhead.d115 # 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 120 103 perfexp--% : driver--%.o observation.o 121 $(COMPILER) $ (EXTRA_COMP_FLAGS) $^ -o $@104 $(COMPILER) $^ -o $@ 122 105 123 106 driver--%.o : driver.c 124 $(COMPILER) $(EXTRA_COMP_FLAGS) -c $< $(OP_DEFINES) -include op-$(OP).h -include fx-$(FX).h -o $@ -MMD 125 126 sayhi: 127 echo $(PERFPROGS) 107 $(COMPILER) -c $< $(OP_DEFINES) -include op-$(OP).h -include fx-$(FX).h -o $@ -MMD 128 108 129 109 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-100137 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-1181 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 endif185 else ifeq "$(RUN_DATA_SIZE_MODE)" "none"186 # Assume user manages RUN_ARGS; empty RUN_ARGS just means run with compiled-in defaults187 RUN_DATA_SIZES=none188 else189 $(error Bad RUN_DATA_SIZE_MODE ($(RUN_DATA_SIZE_MODE)); should be common5, thorough or manual)190 endif191 110 111 112 RUN_NUM_REPS=3 192 113 RUN_REP_IDS=$(shell echo {1..$(RUN_NUM_REPS)}) # 1 2 3 193 114 RUN_REP_EXTS=$(call cross3,,run,$(RUN_REP_IDS),.1csv) # run1.1csv run2.1cav run3.1csv 194 115 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 116 RESULT1S=$(call cross,.,$(CORES),$(RUN_REP_EXTS)) # lq-tailq--stack-inslast-allhead.run2.1csv 201 117 202 118 RESULT1S_SHUFD=$(shell shuf -e $(RESULT1S)) 203 119 204 120 %.1csv : CORE=$(basename $(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 121 %.1csv : REP_ID=$(subst .run,,$(suffix $(basename $@))) 211 122 %.1csv : REP_TIME=$(shell date '+%F %H:%M:%S') 212 123 %.1csv : perfprogs FORCE 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 124 ./perfexp--$(CORE) $(RUNARGS) | xargs -n 1 printf '%s,%s,%s\n' "$(REP_TIME)" "$(REP_ID)" | tee $@ 215 125 216 126 BATCHTIME=$(shell date '+%F--%H-%M-%S') … … 236 146 .PRECIOUS: result--%.1csv driver--%.o perfexp--% %.o 237 147 148 238 149 -include *.d -
doc/theses/mike_brooks_MMath/benchmarks/list/_classic.c
r6e1e2d0 ra50fdfb 171 171 #endif 172 172 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; } 173 174 #define Repeat( op ) for ( volatile unsigned int i = 0; i < NoOfNodes; i += 1 ) { op; } 177 175 178 176 int main() { … … 194 192 TAILQ_INIT(&lst); 195 193 start = clock(); 196 for ( t = 0; t < Times; t += 1 ) {194 for ( volatile unsigned int t = 0; t < Times; t += 1 ) { 197 195 Repeat( TAILQ_INSERT_TAIL( &lst, &s[i], x ) ); 198 196 Repeat( TAILQ_REMOVE( &lst, TAILQ_FIRST( &lst ), x ) ); … … 206 204 std::list<S *> lst; 207 205 start = clock(); 208 for ( t = 0; t < Times; t += 1 ) {206 for ( volatile unsigned int t = 0; t < Times; t += 1 ) { 209 207 Repeat( lst.push_back( &s[i] ) ); 210 208 Repeat( lst.pop_front() ); … … 218 216 uSequence<S> lst; 219 217 start = clock(); 220 for ( t = 0; t < Times; t += 1 ) {218 for ( volatile unsigned int t = 0; t < Times; t += 1 ) { 221 219 Repeat( lst.addTail( &s[i] ) ); 222 220 Repeat( lst.dropHead() ); … … 230 228 dlist(S) lst; 231 229 start = clock(); 232 for ( t = 0; t < Times; t += 1 ) {230 for ( volatile unsigned int t = 0; t < Times; t += 1 ) { 233 231 Repeat( insert_last( lst, s[i] ) ); 234 232 Repeat( remove( lst`first ) ); … … 242 240 Sequence(S) lst; 243 241 start = clock(); 244 for ( t = 0; t < Times; t += 1 ) {242 for ( volatile unsigned int t = 0; t < Times; t += 1 ) { 245 243 Repeat( addHead( lst, s[i] ) ); 246 244 Repeat( dropTail( lst ) ); -
doc/theses/mike_brooks_MMath/benchmarks/list/driver.c
r6e1e2d0 ra50fdfb 17 17 18 18 #if defined(NDEBUG) || (defined(__cforall) && !defined(__CFA_DEBUG__)) 19 enum { DefaultNumNodes = 1000, DefaultExperimentDurSec = 1, DefaultCheck DonePeriod = 1000, DefaultExperimentDurOpCount = -1, DefaultSeed = 5};19 enum { DefaultNumNodes = 1000, DefaultExperimentDurSec = 1, DefaultCheckClockFreq = 1000, DefaultExperimentDurOpCount = -1 }; 20 20 #define TRACE(tp) 21 21 #else 22 enum { DefaultNumNodes = 10, DefaultExperimentDurSec = 1, DefaultCheck DonePeriod = 2, DefaultExperimentDurOpCount = 20, DefaultSeed = 5};22 enum { DefaultNumNodes = 10, DefaultExperimentDurSec = 1, DefaultCheckClockFreq = 2, DefaultExperimentDurOpCount = 20 }; 23 23 static const char * tp_filter 24 24 // = ""; … … 63 63 } 64 64 65 void * bobs_getCurrentLoc() { 66 return BFX_DEREF_POS(B_UserItem, lst, observedItem); 67 } 68 int bobs_getCurrentVal() { 65 int bobs_getCurrent() { 69 66 B_UserItem * curUI = BFX_DEREF_POS(B_UserItem, lst, observedItem); 70 67 return curUI->userdata[17]; … … 75 72 ) 76 73 77 unsigned int uDefaultPreemption() {78 return 0;79 }80 81 74 int main(int argc, const char *argv[]) { 82 75 83 const char * usage_args = "[ExperimentDurSec [CheckDonePeriod [NumNodes [ExperimentDurOpCount [Seed]]]]]"; 84 const int static_arg_posns = 5; 76 77 const char * usage_args = "[ExperimentDurSec [CheckClockFreq [NumNodes [ExperimentDurOpCount]]]]"; 78 const int static_arg_posns = 4; 85 79 86 80 unsigned int ExperimentDurSec = DefaultExperimentDurSec; 87 unsigned int Check DonePeriod = DefaultCheckDonePeriod;81 unsigned int CheckClockFreq = DefaultCheckClockFreq; 88 82 unsigned int NumNodes = DefaultNumNodes; 89 83 size_t ExperimentDurOpCount = DefaultExperimentDurOpCount; 90 unsigned int Seed = DefaultSeed;91 84 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]); 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]); 98 90 } 99 91 100 if (ExperimentDurSec == 0 || Check DonePeriod == 0 || NumNodes == 0 || ExperimentDurOpCount == 0 || Seed== 0 ) {92 if (ExperimentDurSec == 0 || CheckClockFreq == 0 || NumNodes == 0 || ExperimentDurOpCount == 0 ) { 101 93 printf("usage: %s %s\n", argv[0], usage_args); 102 94 return -1; 103 95 } 104 96 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 97 ui = (B_UserItem*) malloc( NumNodes * sizeof(B_UserItem) ); 98 memset(ui, 0, NumNodes * sizeof(B_UserItem)); 111 99 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) 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 122 103 for (int i = 0; i < NumNodes; 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)]; 104 B_UserItem * curUI = & ui[i]; 157 105 curUI->userdata[17] = i; 158 106 } … … 162 110 bobs_init(NumNodes); 163 111 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 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]. 171 115 // Logical insert number 0 and remove number n-1 are given with a distinguished hook. 172 116 // Logical insert numbers [1,n) and remove numbers [0,n-1) are pumped by the basic SUT hooks. 173 117 // 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.)176 118 177 119 // Default init/teardown is insert/remove 178 120 // Cartridges whose SUT insert/remove actions work on empty lists need not provide special-case ones. 179 121 #ifndef BOP_INIT 180 #define BOP_INIT(lst, iters, insNo, item) BOP_INSERT(lst, iters, insNo, item)122 #define BOP_INIT(lst, ui, iters, i) BOP_INSERT(lst, ui, iters, i) 181 123 #endif 182 124 #ifndef BOP_TEARDOWN 183 #define BOP_TEARDOWN(lst, iters, remNo) BOP_REMOVE(lst, iters, remNo)125 #define BOP_TEARDOWN(lst, ui, iters, i) BOP_REMOVE(lst, ui, iters, i) 184 126 #endif 185 127 … … 187 129 clock_t start = clock(); 188 130 189 size_t privateOpsCompleted = 0; 190 191 while (elapsed_sec <= (double) ExperimentDurSec && privateOpsCompleted < ExperimentDurOpCount) { 192 for ( int t = 0; t < CheckDonePeriod; t += 1 ) { 131 while (elapsed_sec <= (double) ExperimentDurSec && bobs_ops_completed < ExperimentDurOpCount) { 132 for ( int t = 0; t < CheckClockFreq; t += 1 ) { 193 133 TRACE('a') 194 134 listedItems[0] = 195 BOP_INIT(lst, listedItems, 0, ui[INSERTPOS(0)]);135 BOP_INIT(lst, ui, listedItems, 0); 196 136 TRACE('b') 197 137 for ( int privateCurInsert = 1; … … 201 141 TRACE('-') 202 142 listedItems[privateCurInsert] = 203 BOP_INSERT( lst, listedItems, privateCurInsert, ui[INSERTPOS(privateCurInsert)]);143 BOP_INSERT( lst, ui, listedItems, privateCurInsert ); 204 144 TRACE('+') 205 145 } … … 210 150 ) { 211 151 TRACE('-') 212 BOP_REMOVE( lst, listedItems, privateCurRemove-1 );152 BOP_REMOVE( lst, ui, listedItems, privateCurRemove-1 ); 213 153 TRACE('+') 214 154 } 215 155 TRACE('D') 216 BOP_TEARDOWN(lst, listedItems, NumNodes-1);156 BOP_TEARDOWN(lst, ui, listedItems, NumNodes-1); 217 157 TRACE('d') 218 219 privateOpsCompleted += NumNodes;220 158 221 159 bobs_prog_rollover_flag = 1; … … 223 161 bobs_prog_inserting = 0; 224 162 bobs_prog_removing = 0; 225 bobs_ops_completed = privateOpsCompleted;163 bobs_ops_completed += NumNodes; 226 164 TRACE('f') 227 165 bobs_prog_rollover_flag = 0; 228 166 TRACE('g') 229 167 } 230 #ifndef DISABLE_CLOCK_RECHECK231 clock_t end = clock();232 elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC);233 #endif234 }235 #ifdef DISABLE_CLOCK_RECHECK236 {237 168 clock_t end = clock(); 238 169 elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC); 239 170 } 240 #endif241 171 242 172 double mean_op_dur_ns = elapsed_sec / ((double)bobs_ops_completed) * 1000 * 1000 * 1000; … … 245 175 free(ui); 246 176 free(listedItems); 247 free(insertOrdShuf);248 177 } -
doc/theses/mike_brooks_MMath/benchmarks/list/observation.c
r6e1e2d0 ra50fdfb 24 24 } 25 25 26 #ifdef BOBS_SHOW_ADDRESSES27 #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 #else33 #define SNAP \34 int userValue = bobs_getCurrentVal();35 #define SHOW(pfx, sfx) \36 printf(" " pfx "%d" sfx, userValue);37 #endif38 26 39 27 static void printPreds(unsigned int leash) { … … 44 32 return; 45 33 } 46 SNAP34 int userValue = bobs_getCurrent(); 47 35 bobs_movePrev(); 48 36 printPreds(leash - 1); 49 SHOW("", "")37 printf(" %d", userValue); 50 38 } 51 39 static void printSuccs(unsigned int leash) { … … 56 44 return; 57 45 } 58 SNAP59 SHOW("", "")46 int userValue = bobs_getCurrent(); 47 printf(" %d", userValue); 60 48 bobs_moveNext(); 61 49 printSuccs(leash - 1); … … 71 59 72 60 bobs_seek(here); 73 SNAP74 SHOW("<", ">")61 int userValue = bobs_getCurrent(); 62 printf(" <%d>", userValue); 75 63 76 64 bobs_moveNext(); -
doc/theses/mike_brooks_MMath/benchmarks/list/observation.h
r6e1e2d0 ra50fdfb 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 void * bobs_getCurrentLoc(); 15 int bobs_getCurrentVal(); 10 void bobs_seek(unsigned int); 11 void bobs_moveNext(); 12 void bobs_movePrev(); 13 int bobs_hasCurrent(); 14 int bobs_getCurrent(); 16 15 17 16 extern volatile size_t bobs_ops_completed; -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-allhead.h
r6e1e2d0 ra50fdfb 3 3 // allhead: inserts and removes happen via the api-provided "last"/"tail"/"back"/"first"/"tail"/"front" 4 4 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-inselem.h
r6e1e2d0 ra50fdfb 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, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item))5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i]) 6 6 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-insfirst-remelem.h
r6e1e2d0 ra50fdfb 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, iters, remNo)BFX_REMOVE_LAST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, ui, iters, i) BFX_REMOVE_LAST(B_UserItem, lst) 6 6 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)])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]) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-allhead.h
r6e1e2d0 ra50fdfb 3 3 // allhead: inserts and removes happen via the api-provided "last"/"tail"/"back"/"first"/"tail"/"front" 4 4 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-inselem.h
r6e1e2d0 ra50fdfb 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, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item))5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i]) 6 6 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-queue-inslast-remelem.h
r6e1e2d0 ra50fdfb 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, iters, remNo)BFX_REMOVE_FIRST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, ui, iters, i) BFX_REMOVE_FIRST(B_UserItem, lst) 6 6 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)])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]) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-allhead.h
r6e1e2d0 ra50fdfb 3 3 // allhead: inserts and removes happen via the api-provided "first"/"head"/"front" 4 4 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-inselem.h
r6e1e2d0 ra50fdfb 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, iters, insNo, item) BFX_INSERT_FIRST(B_UserItem, lst, (item))5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_FIRST(B_UserItem, lst, ui[i]) 6 6 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-insfirst-remelem.h
r6e1e2d0 ra50fdfb 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, iters, remNo)BFX_REMOVE_FIRST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, ui, iters, i) BFX_REMOVE_FIRST(B_UserItem, lst) 6 6 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])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]) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-allhead.h
r6e1e2d0 ra50fdfb 3 3 // allhead: inserts and removes happen via the api-provided "last"/"tail"/"back" 4 4 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-inselem.h
r6e1e2d0 ra50fdfb 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, iters, insNo, item) BFX_INSERT_LAST(B_UserItem, lst, (item))5 #define BOP_INIT(lst, ui, iters, i) BFX_INSERT_LAST(B_UserItem, lst, ui[i]) 6 6 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)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) -
doc/theses/mike_brooks_MMath/benchmarks/list/op-stack-inslast-remelem.h
r6e1e2d0 ra50fdfb 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, iters, remNo)BFX_REMOVE_LAST(B_UserItem, lst)5 #define BOP_TEARDOWN(lst, ui, iters, i) BFX_REMOVE_LAST(B_UserItem, lst) 6 6 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])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]) -
doc/theses/mike_brooks_MMath/benchmarks/list/results-baseline.csv
r6e1e2d0 ra50fdfb 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 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 -
driver/cfa.cc
r6e1e2d0 ra50fdfb 10 10 // Created On : Tue Aug 20 13:44:49 2002 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 21:16:00202313 // Update Count : 47 612 // Last Modified On : Tue Feb 14 22:46:38 2023 13 // Update Count : 470 14 14 // 15 15 … … 44 44 static int flags = 0; 45 45 46 // This allocation 'leaks' memory from the program to the execution47 // environment, as putenv does not manage the storage of the string used48 // as an environment variable. This leak is necessary to ensure the49 // underlying C string is allocated long enough.50 46 if ( putenv( (char *)( *new string( string( __CFA_FLAGPREFIX__ + to_string( flags++ ) + "__=" ) + arg ) ).c_str() ) ) { 51 47 cerr << argv[0] << " error, cannot set environment variable." << endl; … … 202 198 } // if 203 199 } else if ( arg == "-CFA" ) { 204 CFA_flag = true; // strip -CFA flag200 CFA_flag = true; // strip the -CFA flag 205 201 link = false; 206 202 args[nargs++] = "-fsyntax-only"; // stop after stage 2 207 203 } else if ( arg == "-debug" ) { 208 debug = true; // strip debug flag204 debug = true; // strip the debug flag 209 205 } else if ( arg == "-nodebug" ) { 210 debug = false; // strip nodebug flag206 debug = false; // strip the nodebug flag 211 207 } else if ( arg == "-quiet" ) { 212 quiet = true; // strip quiet flag208 quiet = true; // strip the quiet flag 213 209 } else if ( arg == "-noquiet" ) { 214 quiet = false; // strip noquiet flag 215 } else if ( arg == "-invariant" ) { 216 Putenv( argv, "-" + arg ); 217 } else if ( arg == "--invariant" ) { 218 Putenv( argv, arg ); 210 quiet = false; // strip the noquiet flag 219 211 } else if ( arg == "-no-include-stdhdr" ) { 220 noincstd_flag = true; // strip no-include-stdhdr flag212 noincstd_flag = true; // strip the no-include-stdhdr flag 221 213 } else if ( arg == "-nolib" ) { 222 nolib = true; // strip nolib flag214 nolib = true; // strip the nolib flag 223 215 } else if ( arg == "-help" ) { 224 help = true; // strip help flag216 help = true; // strip the help flag 225 217 } else if ( arg == "-nohelp" ) { 226 help = false; // strip nohelp flag218 help = false; // strip the nohelp flag 227 219 } else if ( arg == "-cfalib") { 228 220 compiling_libs = true; … … 282 274 } // if 283 275 } else if ( prefix( arg, "-B" ) ) { 284 bprefix = arg.substr(2); // strip -B flag276 bprefix = arg.substr(2); // strip the -B flag 285 277 } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) { 286 278 args[nargs++] = argv[i]; // pass flag along -
src/AST/Attribute.hpp
r6e1e2d0 ra50fdfb 27 27 class Expr; 28 28 29 /// An entry in an attribute list: `__attribute__(( ... ))`30 29 class Attribute final : public Node { 31 30 public: -
src/AST/Convert.cpp
r6e1e2d0 ra50fdfb 559 559 auto stmt = new SuspendStmt(); 560 560 stmt->then = get<CompoundStmt>().accept1( node->then ); 561 switch (node->kind) {561 switch(node->type) { 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->isVarArgs) ? ast::VariableArgs : ast::FixedArgs1697 old->type->isVarArgs 1698 1698 }; 1699 1699 … … 2001 2001 GET_ACCEPT_1(else_, Stmt), 2002 2002 GET_ACCEPT_V(initialization, Stmt), 2003 (old->isDoWhile) ? ast::DoWhile : ast::While,2003 old->isDoWhile, 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:: Kindtype;2145 ast::SuspendStmt::Type type; 2146 2146 switch (old->type) { 2147 2147 case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break; -
src/AST/Decl.cpp
r6e1e2d0 ra50fdfb 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, ArgumentFlag isVarArgs)59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool 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( isVarArgs);63 FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(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, ArgumentFlag isVarArgs)83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool 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 );88 FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs ); 89 89 for ( auto & param : this->params ) { 90 90 type->params.emplace_back( param->get_type() ); -
src/AST/Decl.hpp
r6e1e2d0 ra50fdfb 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 5 10:42:00 202313 // Update Count : 3 512 // Last Modified On : Thu Nov 24 9:44:00 2022 13 // Update Count : 34 14 14 // 15 15 … … 122 122 }; 123 123 124 /// Function variable arguments flag125 enum ArgumentFlag { FixedArgs, VariableArgs };126 127 124 /// Object declaration `int foo()` 128 125 class FunctionDecl : public DeclWithType { … … 147 144 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 148 145 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 149 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs);146 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false); 150 147 151 148 FunctionDecl( const CodeLocation & location, const std::string & name, … … 153 150 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 154 151 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 155 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs);152 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false); 156 153 157 154 const Type * get_type() const override; … … 316 313 public: 317 314 bool isTyped; // isTyped indicated if the enum has a declaration like: 318 // enum (type_optional) Name {...} 315 // enum (type_optional) Name {...} 319 316 ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum 320 317 enum class EnumHiding { Visible, Hide } hide; … … 374 371 }; 375 372 376 /// Assembly declaration: `asm ... ( "..." : ... )`377 373 class AsmDecl : public Decl { 378 374 public: -
src/AST/Expr.hpp
r6e1e2d0 ra50fdfb 254 254 }; 255 255 256 /// A name qualified by a namespace or type.257 256 class QualifiedNameExpr final : public Expr { 258 257 public: … … 260 259 std::string name; 261 260 262 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 261 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 263 262 : Expr( loc ), type_decl( d ), name( n ) {} 264 263 … … 622 621 }; 623 622 624 /// A name that refers to a generic dimension parameter.625 623 class DimensionExpr final : public Expr { 626 624 public: … … 912 910 }; 913 911 912 914 913 } 915 914 -
src/AST/Init.hpp
r6e1e2d0 ra50fdfb 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
r6e1e2d0 ra50fdfb 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Apr 14 15:09:00 202313 // Update Count : 412 // Last Modified On : Mon Oct 3 11:04:00 2022 13 // Update Count : 3 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 174 170 } // namespace ast -
src/AST/Inspect.hpp
r6e1e2d0 ra50fdfb 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Apr 14 15:09:00 202313 // Update Count : 312 // Last Modified On : Thr Sep 22 13:44:00 2022 13 // Update Count : 2 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 43 40 } -
src/AST/Pass.impl.hpp
r6e1e2d0 ra50fdfb 2075 2075 if ( __visit_children() ) { 2076 2076 maybe_accept( node, &TupleType::types ); 2077 maybe_accept( node, &TupleType::members ); 2077 2078 } 2078 2079 -
src/AST/Print.cpp
r6e1e2d0 ra50fdfb 766 766 virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final { 767 767 os << "Suspend Statement"; 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;768 switch (node->type) { 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
r6e1e2d0 ra50fdfb 10 10 // Created On : Wed May 8 13:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 5 10:34:00 202313 // Update Count : 3 712 // Last Modified On : Wed Apr 20 14:34:00 2022 13 // Update Count : 36 14 14 // 15 15 … … 205 205 }; 206 206 207 // A while loop or a do-while loop:208 enum WhileDoKind { While, DoWhile };209 210 207 // While loop: while (...) ... else ... or do ... while (...) else ...; 211 208 class WhileDoStmt final : public Stmt { … … 215 212 ptr<Stmt> else_; 216 213 std::vector<ptr<Stmt>> inits; 217 WhileDoKindisDoWhile;214 bool isDoWhile; 218 215 219 216 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, 220 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )217 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} ) 221 218 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {} 222 219 223 220 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_, 224 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )221 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} ) 225 222 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {} 226 223 … … 367 364 public: 368 365 ptr<CompoundStmt> then; 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) {}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) {} 373 370 374 371 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } … … 427 424 }; 428 425 429 // Clause in a waitfor statement: waitfor (..., ...) ...430 426 class WaitForClause final : public WhenClause { 431 427 public: … … 531 527 MUTATE_FRIEND 532 528 }; 533 534 529 } // namespace ast 535 530 -
src/AST/SymbolTable.cpp
r6e1e2d0 ra50fdfb 260 260 void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) { 261 261 // default handling of conflicts is to raise an error 262 addId Common( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );262 addId( 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 Common( decl, OnConflict::error(), nullptr, deleter );267 addId( decl, OnConflict::error(), nullptr, deleter ); 268 268 } 269 269 … … 677 677 } 678 678 679 void SymbolTable::addId Common(680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, 681 const Expr * baseExpr, constDecl * deleter ) {679 void SymbolTable::addId( 680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 681 const Decl * deleter ) { 682 682 SpecialFunctionKind kind = getSpecialFunctionKind(decl->name); 683 683 if (kind == NUMBER_OF_KINDS) { // not a special decl 684 addId ToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);684 addId(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 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 ) { 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 ) { 705 704 ++*stats().add_calls; 706 705 const std::string &name = decl->name; … … 779 778 void SymbolTable::addMembers( 780 779 const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) { 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 );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 } 799 798 } 800 799 } -
src/AST/SymbolTable.hpp
r6e1e2d0 ra50fdfb 192 192 193 193 /// common code for addId, addDeletedId, etc. 194 void addId Common(195 const DeclWithType * decl, OnConflict handleConflicts, 196 const Expr * baseExpr = nullptr, constDecl * deleter = nullptr );194 void addId( 195 const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr, 196 const Decl * deleter = nullptr ); 197 197 198 198 /// common code for addId when special decls are placed into separate tables 199 void addIdToTable( 200 const DeclWithType * decl, const std::string & lookupKey, 201 IdTable::Ptr & idTable, OnConflict handleConflicts, 199 void addId( 200 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts, 202 201 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr); 203 202 204 203 /// adds all of the members of the Aggregate (addWith helper) 205 204 void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts ); -
src/AST/Type.cpp
r6e1e2d0 ra50fdfb 10 10 // Created On : Mon May 13 15:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 6 15:59:00 202313 // Update Count : 712 // Last Modified On : Thu Nov 24 9:49:00 2022 13 // Update Count : 6 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) ) {} 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 } 202 220 203 221 bool isUnboundType(const Type * type) { -
src/AST/Type.hpp
r6e1e2d0 ra50fdfb 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 6 15:58:00 202313 // Update Count : 912 // Last Modified On : Thu Nov 24 9:47:00 2022 13 // Update Count : 8 14 14 // 15 15 … … 265 265 }; 266 266 267 /// Function variable arguments flag 268 enum ArgumentFlag { FixedArgs, VariableArgs }; 269 267 270 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 268 271 class FunctionType final : public Type { … … 457 460 public: 458 461 std::vector<ptr<Type>> types; 462 std::vector<ptr<Decl>> members; 459 463 460 464 TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} ); -
src/Common/CodeLocationTools.cpp
r6e1e2d0 ra50fdfb 210 210 211 211 struct LeafKindVisitor : public ast::Visitor { 212 LeafKind result;212 LeafKind kind; 213 213 214 214 #define VISIT(node_type, return_type) \ 215 215 const ast::return_type * visit( const ast::node_type * ) final { \ 216 result= LeafKind::node_type; \216 kind = LeafKind::node_type; \ 217 217 return nullptr; \ 218 218 } … … 224 224 225 225 LeafKind get_leaf_kind( ast::Node const * node ) { 226 return ast::Pass<LeafKindVisitor>::read( node ); 226 LeafKindVisitor visitor; 227 node->accept( visitor ); 228 return visitor.kind; 227 229 } 228 230 -
src/Common/Iterate.hpp
r6e1e2d0 ra50fdfb 20 20 #include <iterator> 21 21 22 // Returns an iterator that is it advanced n times.22 // it's nice to actually be able to increment iterators by an arbitrary amount 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 support53 // for ( val_and_index : enumerate( container ) ) {}54 // which iterates through the container and tracks the index as well.55 56 52 template< typename T > 57 53 struct enumerate_t { … … 113 109 114 110 // ----------------------------------------------------------------------------- 115 // Helper function to transform one iterable container into another.116 117 111 template< typename OutType, typename Range, typename Functor > 118 112 OutType map_range( const Range& range, Functor&& functor ) { … … 212 206 // Helper struct and function to support 213 207 // for ( val : lazy_map( container1, f ) ) {} 214 // syntax to have a for each that iterates a container, 215 // mapping each element by applying f. 216 208 // syntax to have a for each that iterates a container, mapping each element by applying f 217 209 template< typename T, typename Func > 218 210 struct lambda_iterate_t { -
src/CompilationState.cc
r6e1e2d0 ra50fdfb 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Apr 10 19:12:50 202313 // Update Count : 611 // Last Modified By : Henry Xue 12 // Last Modified On : Tue Jul 20 04:27:35 2021 13 // Update Count : 5 14 14 // 15 15 … … 27 27 expraltp = false, 28 28 genericsp = false, 29 invariant = false,30 29 libcfap = false, 31 30 nopreludep = false, -
src/CompilationState.h
r6e1e2d0 ra50fdfb 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Apr 10 19:12:53 202313 // Update Count : 611 // Last Modified By : Henry Xue 12 // Last Modified On : Tue Jul 20 04:27:35 2021 13 // Update Count : 5 14 14 // 15 15 … … 26 26 expraltp, 27 27 genericsp, 28 invariant,29 28 libcfap, 30 29 nopreludep, -
src/Concurrency/KeywordsNew.cpp
r6e1e2d0 ra50fdfb 779 779 780 780 const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) { 781 switch ( stmt-> kind) {781 switch ( stmt->type ) { 782 782 case ast::SuspendStmt::None: 783 783 // Use the context to determain the implicit target. -
src/InitTweak/FixInitNew.cpp
r6e1e2d0 ra50fdfb 14 14 #include <utility> // for pair 15 15 16 #include "AST/DeclReplacer.hpp"17 #include "AST/Expr.hpp"18 16 #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"24 17 #include "CodeGen/GenType.h" // for genPrettyType 25 18 #include "CodeGen/OperatorTable.h" 19 #include "Common/CodeLocationTools.hpp" 26 20 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 27 21 #include "Common/SemanticError.h" // for SemanticError … … 34 28 #include "ResolvExpr/Unify.h" // for typesCompatible 35 29 #include "SymTab/Autogen.h" // for genImplicitCall 36 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall37 30 #include "SymTab/Indexer.h" // for Indexer 38 31 #include "SymTab/Mangler.h" // for Mangler … … 52 45 #include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy 53 46 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 54 55 extern bool ctordtorp; // print all debug 55 56 extern bool ctorp; // print ctor debug … … 62 63 namespace InitTweak { 63 64 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::Cforall90 );91 return new ast::FunctionDecl( loc,92 fname,93 std::move(typeParams),94 {dstParam},95 {},96 new ast::CompoundStmt(loc),97 {},98 ast::Linkage::Cforall99 );100 }101 102 65 struct SelfAssignChecker { 103 66 void previsit( const ast::ApplicationExpr * appExpr ); … … 158 121 void previsit( const ast::FunctionDecl * ) { visit_children = false; } 159 122 160 protected:123 protected: 161 124 ObjectSet curVars; 162 125 }; … … 239 202 240 203 SemanticErrorException errors; 241 private:204 private: 242 205 template< typename... Params > 243 206 void emit( CodeLocation, const Params &... params ); … … 325 288 static UniqueName dtorNamer( "__cleanup_dtor" ); 326 289 std::string name = dtorNamer.newName(); 327 ast::FunctionDecl * dtorFunc = genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );290 ast::FunctionDecl * dtorFunc = SymTab::genDefaultFunc( loc, name, objDecl->type->stripReferences(), false ); 328 291 stmtsToAdd.push_back( new ast::DeclStmt(loc, dtorFunc ) ); 329 292 … … 1117 1080 void InsertDtors::previsit( const ast::BranchStmt * stmt ) { 1118 1081 switch( stmt->kind ) { 1119 case ast::BranchStmt::Continue:1120 case ast::BranchStmt::Break:1082 case ast::BranchStmt::Continue: 1083 case ast::BranchStmt::Break: 1121 1084 // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should 1122 1085 // always be empty), but it serves as a small sanity check. 1123 case ast::BranchStmt::Goto:1086 case ast::BranchStmt::Goto: 1124 1087 handleGoto( stmt ); 1125 1088 break; 1126 default:1089 default: 1127 1090 assert( false ); 1128 1091 } // switch … … 1349 1312 // xxx - functions returning ast::ptr seems wrong... 1350 1313 auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } ); 1351 return res.release(); 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 ); 1352 1317 } 1353 1318 -
src/InitTweak/GenInit.cc
r6e1e2d0 ra50fdfb 39 39 #include "ResolvExpr/Resolver.h" 40 40 #include "SymTab/Autogen.h" // for genImplicitCall 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall42 41 #include "SymTab/Mangler.h" // for Mangler 43 42 #include "SynTree/LinkageSpec.h" // for isOverridable, C -
src/Parser/DeclarationNode.cc
r6e1e2d0 ra50fdfb 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T hr Apr 20 11:46:00 202313 // Update Count : 139 312 // Last Modified On : Tue Apr 4 10:28:00 2023 13 // Update Count : 1392 14 14 // 15 16 #include "DeclarationNode.h"17 15 18 16 #include <cassert> // for assert, assertf, strict_dynamic_cast … … 36 34 #include "Common/UniqueName.h" // for UniqueName 37 35 #include "Common/utility.h" // for maybeClone 38 #include "Parser/ExpressionNode.h" // for ExpressionNode 39 #include "Parser/InitializerNode.h"// for InitializerNode 40 #include "Parser/StatementNode.h" // for StatementNode 36 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 41 37 #include "TypeData.h" // for TypeData, TypeData::Aggregate_t 42 38 #include "TypedefTable.h" // for TypedefTable … … 1003 999 } 1004 1000 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, 1001 void buildList( const DeclarationNode * firstNode, 1088 1002 std::vector<ast::ptr<ast::Decl>> & outputList ) { 1089 1003 SemanticErrorException errors; 1090 1004 std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList ); 1091 1005 1092 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur) ) {1006 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) { 1093 1007 try { 1094 bool extracted _named= false;1095 ast:: UnionDecl * unionDecl = nullptr;1008 bool extracted = false, anon = false; 1009 ast::AggregateDecl * unionDecl = nullptr; 1096 1010 1097 1011 if ( DeclarationNode * extr = cur->extractAggregate() ) { 1012 // Handle the case where a SUE declaration is contained within an object or type declaration. 1013 1098 1014 assert( cur->type ); 1099 nameTypedefedDecl( extr, cur ); 1100 1101 if ( ast::Decl * decl = extr->build() ) { 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 ) { 1102 1048 // Remember the declaration if it is a union aggregate ? 1103 1049 unionDecl = dynamic_cast<ast::UnionDecl *>( decl ); 1104 1050 1051 decl->location = cur->location; 1105 1052 *out++ = decl; 1106 1053 1107 1054 // need to remember the cases where a declaration contains an anonymous aggregate definition 1055 extracted = true; 1108 1056 assert( extr->type ); 1109 1057 if ( extr->type->kind == TypeData::Aggregate ) { 1110 1058 // typedef struct { int A } B is the only case? 1111 extracted_named = !extr->type->aggregate.anon;1059 anon = extr->type->aggregate.anon; 1112 1060 } else if ( extr->type->kind == TypeData::Enum ) { 1113 1061 // typedef enum { A } B is the only case? 1114 extracted_named = !extr->type->enumeration.anon; 1115 } else { 1116 extracted_named = true; 1062 anon = extr->type->enumeration.anon; 1117 1063 } 1118 1064 } // if … … 1120 1066 } // if 1121 1067 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 } 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 1142 1097 } // if 1143 *out++ = decl; 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 1144 1122 } // if 1145 } catch ( SemanticErrorException & e ) {1123 } catch( SemanticErrorException & e ) { 1146 1124 errors.append( e ); 1147 1125 } // try … … 1154 1132 1155 1133 // currently only builds assertions, function parameters, and return values 1156 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {1134 void buildList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) { 1157 1135 SemanticErrorException errors; 1158 1136 std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList ); 1159 1137 1160 for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur) ) {1138 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) { 1161 1139 try { 1162 1140 ast::Decl * decl = cur->build(); 1163 assert f( decl, "buildList: build for ast::DeclWithType.");1141 assert( decl ); 1164 1142 if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1165 1143 dwt->location = cur->location; … … 1190 1168 ); 1191 1169 *out++ = obj; 1192 } else {1193 assertf( false, "buildList: Could not convert to ast::DeclWithType." );1194 1170 } // if 1195 } catch ( SemanticErrorException & e ) {1171 } catch( SemanticErrorException & e ) { 1196 1172 errors.append( e ); 1197 1173 } // try … … 1207 1183 SemanticErrorException errors; 1208 1184 std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList ); 1209 1210 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1185 const DeclarationNode * cur = firstNode; 1186 1187 while ( cur ) { 1211 1188 try { 1212 1189 * out++ = cur->buildType(); 1213 } catch ( SemanticErrorException & e ) {1190 } catch( SemanticErrorException & e ) { 1214 1191 errors.append( e ); 1215 1192 } // try 1216 } // for 1193 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 1194 } // while 1217 1195 1218 1196 if ( ! errors.isEmpty() ) { -
src/Parser/ExpressionNode.cc
r6e1e2d0 ra50fdfb 13 13 // Update Count : 1083 14 14 // 15 16 #include "ExpressionNode.h"17 15 18 16 #include <cassert> // for assert … … 27 25 #include "Common/SemanticError.h" // for SemanticError 28 26 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 29 #include "DeclarationNode.h" // for DeclarationNode 30 #include "InitializerNode.h" // for InitializerNode 27 #include "ParseNode.h" // for ExpressionNode, maybeMoveBuildType 31 28 #include "parserutility.h" // for notZeroExpr 32 29 … … 702 699 } // build_binary_val 703 700 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_ptr 707 704 708 ast::Expr * build_cond( const CodeLocation & location, 705 709 ExpressionNode * expr_node1, -
src/Parser/InitializerNode.cc
r6e1e2d0 ra50fdfb 14 14 // 15 15 16 #include "InitializerNode.h"17 18 16 #include <iostream> // for operator<<, ostream, basic_ostream 19 17 #include <list> // for list 20 18 #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 "ExpressionNode.h" // for ExpressionNode 27 #include "DeclarationNode.h" // for buildList 28 29 using namespace std; 26 #include "ParseNode.h" // for InitializerNode, ExpressionNode 30 27 31 28 static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) { -
src/Parser/ParseNode.h
r6e1e2d0 ra50fdfb 38 38 class DeclarationWithType; 39 39 class Initializer; 40 class InitializerNode;41 40 class ExpressionNode; 42 41 struct StatementNode; … … 80 79 CodeLocation location = yylloc; 81 80 }; // ParseNode 81 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 list 112 InitializerNode * kids; 113 bool maybeConstructed; 114 bool isDelete; 115 }; // InitializerNode 116 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 }; // ExpressionNode 82 152 83 153 // Must harmonize with OperName. … … 99 169 }; 100 170 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 NoBasicType 213 }; 214 static const char * basicTypeNames[]; 215 enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message 216 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 attributes 256 static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement 257 static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement 258 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 functions 286 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 }; // DeclarationNode 352 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 }; // StatementNode 398 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 } // if 468 } catch( SemanticErrorException & e ) { 469 errors.append( e ); 470 } // try 471 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 } // if 477 } // while 478 if ( ! errors.isEmpty() ) { 479 throw errors; 480 } // if 481 } 482 483 // in DeclarationNode.cc 484 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.cc 101 497 std::ostream & operator<<( std::ostream & out, const ParseNode * node ); 102 498 -
src/Parser/RunParser.cpp
r6e1e2d0 ra50fdfb 20 20 #include "CodeTools/TrackLoc.h" // for fillLocations 21 21 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 22 #include "Parser/ DeclarationNode.h"// for DeclarationNode, buildList22 #include "Parser/ParseNode.h" // for DeclarationNode, buildList 23 23 #include "Parser/TypedefTable.h" // for TypedefTable 24 24 -
src/Parser/StatementNode.cc
r6e1e2d0 ra50fdfb 11 11 // Created On : Sat May 16 14:59:41 2015 12 12 // Last Modified By : Andrew Beach 13 // Last Modified On : Tue Apr 11 10:16:00 202314 // Update Count : 42 813 // Last Modified On : Tue Apr 4 11:40:00 2023 14 // Update Count : 427 15 15 // 16 17 #include "StatementNode.h"18 16 19 17 #include <cassert> // for assert, strict_dynamic_cast, assertf … … 25 23 #include "Common/SemanticError.h" // for SemanticError 26 24 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild 27 #include "DeclarationNode.h" // for DeclarationNode 28 #include "ExpressionNode.h" // for ExpressionNode 25 #include "ParseNode.h" // for StatementNode, ExpressionNode, bui... 29 26 #include "parserutility.h" // for notZeroExpr 30 27 … … 32 29 33 30 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 }49 31 50 32 StatementNode::StatementNode( DeclarationNode * decl ) { … … 71 53 } // StatementNode::StatementNode 72 54 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; 55 StatementNode * StatementNode::append_last_case( StatementNode * stmt ) { 56 StatementNode * prev = this; 88 57 // find end of list and maintain previous pointer 89 for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) { 90 ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr); 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() ); 91 61 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) ); 92 62 prev = curr; 93 63 } // for 94 ClauseNode * node = dynamic_cast< ClauseNode * >(prev);95 64 // convert from StatementNode list to Statement list 65 StatementNode * node = dynamic_cast< StatementNode * >(prev); 96 66 std::vector<ast::ptr<ast::Stmt>> stmts; 97 67 buildMoveList( stmt, stmts ); … … 103 73 stmts.clear(); 104 74 return this; 105 } // ClauseNode::append_last_case75 } // StatementNode::append_last_case 106 76 107 77 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) { … … 127 97 for ( ast::ptr<ast::Stmt> & stmt : inits ) { 128 98 // build the && of all of the declared variables compared against 0 99 //auto declStmt = strict_dynamic_cast<ast::DeclStmt *>( stmt ); 129 100 auto declStmt = stmt.strict_as<ast::DeclStmt>(); 101 //ast::DeclWithType * dwt = strict_dynamic_cast<ast::DeclWithType *>( declStmt->decl ); 130 102 auto dwt = declStmt->decl.strict_as<ast::DeclWithType>(); 131 103 ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) ); … … 141 113 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 142 114 143 ast::Stmt const * astthen = buildMoveSingle( then ); 144 ast::Stmt const * astelse = buildMoveOptional( else_ ); 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 145 127 146 128 return new ast::IfStmt( location, astcond, astthen, astelse, … … 149 131 } // build_if 150 132 151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) { 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 ) { 152 169 std::vector<ast::ptr<ast::CaseClause>> aststmt; 153 buildMove List( stmt, aststmt );170 buildMoveClauseList( stmt, aststmt ); 154 171 // If it is not a switch it is a choose statement. 155 172 if ( ! isSwitch ) { … … 173 190 } // build_switch 174 191 175 ast::CaseClause * build_case( const CodeLocation & location,ExpressionNode * ctl ) {192 ast::CaseClause * build_case( ExpressionNode * ctl ) { 176 193 // stmt starts empty and then added to 177 194 auto expr = maybeMoveBuild( ctl ); 178 return new ast::CaseClause( location, expr, {} );195 return new ast::CaseClause( expr->location, expr, {} ); 179 196 } // build_case 180 197 … … 188 205 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 189 206 207 std::vector<ast::ptr<ast::Stmt>> aststmt; // loop body, compound created if empty 208 buildMoveList( stmt, aststmt ); 209 assert( aststmt.size() == 1 ); 210 211 std::vector<ast::ptr<ast::Stmt>> astelse; // else clause, maybe empty 212 buildMoveList( else_, astelse ); 213 assert( astelse.size() <= 1 ); 214 190 215 return new ast::WhileDoStmt( location, 191 216 astcond, 192 buildMoveSingle( stmt),193 buildMoveOptional( else_),217 aststmt.front(), 218 astelse.empty() ? nullptr : astelse.front().release(), 194 219 std::move( astinit ), 195 ast::While220 false 196 221 ); 197 222 } // build_while 198 223 199 224 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 empty 226 buildMoveList( stmt, aststmt ); 227 assert( aststmt.size() == 1 ); // compound created if empty 228 229 std::vector<ast::ptr<ast::Stmt>> astelse; // else clause, maybe empty 230 buildMoveList( else_, astelse ); 231 assert( astelse.size() <= 1 ); 232 200 233 // do-while cannot have declarations in the contitional, so init is always empty 201 234 return new ast::WhileDoStmt( location, 202 235 notZeroExpr( maybeMoveBuild( ctl ) ), 203 buildMoveSingle( stmt),204 buildMoveOptional( else_),236 aststmt.front(), 237 astelse.empty() ? nullptr : astelse.front().release(), 205 238 {}, 206 ast::DoWhile239 true 207 240 ); 208 241 } // build_do_while … … 218 251 astincr = maybeMoveBuild( forctl->change ); 219 252 delete forctl; 253 254 std::vector<ast::ptr<ast::Stmt>> aststmt; // loop body, compound created if empty 255 buildMoveList( stmt, aststmt ); 256 assert( aststmt.size() == 1 ); 257 258 std::vector<ast::ptr<ast::Stmt>> astelse; // else clause, maybe empty 259 buildMoveList( else_, astelse ); 260 assert( astelse.size() <= 1 ); 220 261 221 262 return new ast::ForStmt( location, … … 223 264 astcond, 224 265 astincr, 225 buildMoveSingle( stmt),226 buildMoveOptional( else_)266 aststmt.front(), 267 astelse.empty() ? nullptr : astelse.front().release() 227 268 ); 228 269 } // build_for … … 285 326 } // build_resume_at 286 327 287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {328 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) { 288 329 std::vector<ast::ptr<ast::CatchClause>> aststmt; 289 buildMove List( catch_, aststmt );330 buildMoveClauseList( catch_, aststmt ); 290 331 ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) ); 291 332 ast::FinallyClause * finallyBlock = nullptr; … … 301 342 302 343 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 ); 303 347 return new ast::CatchClause( location, 304 348 kind, 305 349 maybeMoveBuild( decl ), 306 350 maybeMoveBuild( cond ), 307 buildMoveSingle( body)351 aststmt.front().release() 308 352 ); 309 353 } // build_catch 310 354 311 355 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 ); 312 359 return new ast::FinallyClause( location, 313 strict_dynamic_cast<const ast::CompoundStmt *>( 314 buildMoveSingle( stmt ) 315 ) 360 aststmt.front().strict_as<ast::CompoundStmt>() 316 361 ); 317 362 } // build_finally 318 363 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 ); 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; 326 375 } // build_suspend 327 376 … … 476 525 477 526 // Question 478 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode* instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {527 ast::Stmt * build_asm( const CodeLocation & location, bool voltile, ast::Expr * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) { 479 528 std::vector<ast::ptr<ast::Expr>> out, in; 480 529 std::vector<ast::ptr<ast::ConstantExpr>> clob; … … 484 533 buildMoveList( clobber, clob ); 485 534 return new ast::AsmStmt( location, 486 is_volatile,487 maybeMoveBuild( instruction ),535 voltile, 536 instruction, 488 537 std::move( out ), 489 538 std::move( in ), -
src/Parser/TypeData.cc
r6e1e2d0 ra50fdfb 24 24 #include "Common/SemanticError.h" // for SemanticError 25 25 #include "Common/utility.h" // for splice, spliceBegin 26 #include "Parser/ ExpressionNode.h" // for ExpressionNode27 #include "Parser/ StatementNode.h" // for StatementNode26 #include "Parser/parserutility.h" // for maybeCopy, maybeBuild, maybeMoveB... 27 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 28 28 29 29 class Attribute; … … 1397 1397 std::move( attributes ), 1398 1398 funcSpec, 1399 (isVarArgs) ? ast::VariableArgs : ast::FixedArgs1399 isVarArgs 1400 1400 ); 1401 1401 buildList( td->function.withExprs, decl->withExprs ); -
src/Parser/TypeData.h
r6e1e2d0 ra50fdfb 16 16 #pragma once 17 17 18 #include <iosfwd> // for ostream19 #include <list> // for list20 #include <string> // for string18 #include <iosfwd> // for ostream 19 #include <list> // for list 20 #include <string> // for string 21 21 22 #include "AST/Type.hpp" // for Type23 #include " DeclarationNode.h" // for DeclarationNode22 #include "AST/Type.hpp" // for Type 23 #include "ParseNode.h" // for DeclarationNode, DeclarationNode::Ag... 24 24 25 25 struct TypeData { -
src/Parser/TypedefTable.cc
r6e1e2d0 ra50fdfb 16 16 17 17 #include "TypedefTable.h" 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 18 #include <cassert> // for assert 19 #include <iostream> 29 20 using namespace std; 30 21 31 22 #if 0 32 23 #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 } // switch44 } // kindName45 24 #else 46 25 #define debugPrint( code ) 47 26 #endif 27 28 using namespace std; // string, iostream 29 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 } // switch 41 } // kindName 42 ); 48 43 49 44 TypedefTable::~TypedefTable() { … … 83 78 typedefTable.addToEnclosingScope( name, kind, "MTD" ); 84 79 } // if 85 } // TypedefTable::makeTypedef86 87 void TypedefTable::makeTypedef( const string & name ) {88 return makeTypedef( name, TYPEDEFname );89 80 } // TypedefTable::makeTypedef 90 81 -
src/Parser/TypedefTable.h
r6e1e2d0 ra50fdfb 19 19 20 20 #include "Common/ScopedMap.h" // for ScopedMap 21 #include "ParserTypes.h" 22 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname 21 23 22 24 class TypedefTable { 23 25 struct Note { size_t level; bool forall; }; 24 26 typedef ScopedMap< std::string, int, Note > KindTable; 25 KindTable kindTable; 27 KindTable kindTable; 26 28 unsigned int level = 0; 27 29 public: … … 31 33 bool existsCurr( const std::string & identifier ) const; 32 34 int isKind( const std::string & identifier ) const; 33 void makeTypedef( const std::string & name, int kind ); 34 void makeTypedef( const std::string & name ); 35 void makeTypedef( const std::string & name, int kind = TYPEDEFname ); 35 36 void addToScope( const std::string & identifier, int kind, const char * ); 36 37 void addToEnclosingScope( const std::string & identifier, int kind, const char * ); -
src/Parser/lex.ll
r6e1e2d0 ra50fdfb 44 44 45 45 #include "config.h" // configure info 46 #include "DeclarationNode.h" // for DeclarationNode47 #include "ExpressionNode.h" // for LabelNode48 #include "InitializerNode.h" // for InitializerNode49 46 #include "ParseNode.h" 50 #include "ParserTypes.h" // for Token51 #include "StatementNode.h" // for CondCtl, ForCtrl52 47 #include "TypedefTable.h" 53 // This (generated) header must come late as it is missing includes.54 #include "parser.hh" // generated info55 48 56 49 string * build_postfix_name( string * name ); -
src/Parser/module.mk
r6e1e2d0 ra50fdfb 21 21 SRC += \ 22 22 Parser/DeclarationNode.cc \ 23 Parser/DeclarationNode.h \24 23 Parser/ExpressionNode.cc \ 25 Parser/ExpressionNode.h \26 24 Parser/InitializerNode.cc \ 27 Parser/InitializerNode.h \28 25 Parser/lex.ll \ 29 26 Parser/ParseNode.cc \ … … 36 33 Parser/RunParser.hpp \ 37 34 Parser/StatementNode.cc \ 38 Parser/StatementNode.h \39 35 Parser/TypeData.cc \ 40 36 Parser/TypeData.h \ -
src/Parser/parser.yy
r6e1e2d0 ra50fdfb 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Apr 26 16:45:37202313 // Update Count : 63 3011 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 14:02:00 2023 13 // Update Count : 6329 14 14 // 15 15 … … 48 48 using namespace std; 49 49 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_... 50 #include "SynTree/Declaration.h" 51 #include "ParseNode.h" 56 52 #include "TypedefTable.h" 57 53 #include "TypeData.h" 54 #include "SynTree/LinkageSpec.h" 58 55 #include "Common/SemanticError.h" // error_str 59 56 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... … … 300 297 %union { 301 298 Token tok; 302 ExpressionNode * expr; 299 ParseNode * pn; 300 ExpressionNode * en; 303 301 DeclarationNode * decl; 304 302 ast::AggregateDecl::Aggregate aggKey; 305 303 ast::TypeDecl::Kind tclass; 306 StatementNode * stmt; 307 ClauseNode * clause; 304 StatementNode * sn; 308 305 ast::WaitForStmt * wfs; 309 ast::WaitUntilStmt::ClauseNode * wucn; 306 ast::WaitUntilStmt::ClauseNode * wuscn; 307 ast::Expr * constant; 310 308 CondCtl * ifctl; 311 ForCtrl * forctl; 312 LabelNode * labels; 313 InitializerNode * init; 314 OperKinds oper; 309 ForCtrl * fctl; 310 OperKinds compop; 311 LabelNode * label; 312 InitializerNode * in; 313 OperKinds op; 315 314 std::string * str; 316 bool is_volatile;317 EnumHiding enum_hiding;318 ast::ExceptionKind except_kind;315 bool flag; 316 EnumHiding hide; 317 ast::ExceptionKind catch_kind; 319 318 ast::GenericExpr * genexpr; 320 319 } … … 382 381 %type<tok> identifier identifier_at identifier_or_type_name attr_name 383 382 %type<tok> quasi_keyword 384 %type< expr> string_literal383 %type<constant> string_literal 385 384 %type<str> string_literal_list 386 385 387 %type< enum_hiding> hide_opt visible_hide_opt386 %type<hide> hide_opt visible_hide_opt 388 387 389 388 // expressions 390 %type<e xpr> constant391 %type<e xpr> tuple tuple_expression_list392 %type<op er> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator393 %type<e xpr> primary_expression postfix_expression unary_expression394 %type<e xpr> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression395 %type<e xpr> shift_expression relational_expression equality_expression396 %type<e xpr> AND_expression exclusive_OR_expression inclusive_OR_expression397 %type<e xpr> logical_AND_expression logical_OR_expression398 %type<e xpr> conditional_expression constant_expression assignment_expression assignment_expression_opt399 %type<e xpr> comma_expression comma_expression_opt400 %type<e xpr> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt389 %type<en> constant 390 %type<en> tuple tuple_expression_list 391 %type<op> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator 392 %type<en> primary_expression postfix_expression unary_expression 393 %type<en> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression 394 %type<en> shift_expression relational_expression equality_expression 395 %type<en> AND_expression exclusive_OR_expression inclusive_OR_expression 396 %type<en> logical_AND_expression logical_OR_expression 397 %type<en> conditional_expression constant_expression assignment_expression assignment_expression_opt 398 %type<en> comma_expression comma_expression_opt 399 %type<en> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt 401 400 %type<ifctl> conditional_declaration 402 %type<f orctl> for_control_expression for_control_expression_list403 %type< oper> upupeq updown updowneq downupdowneq404 %type<e xpr> subrange401 %type<fctl> for_control_expression for_control_expression_list 402 %type<compop> upupeq updown updowneq downupdowneq 403 %type<en> subrange 405 404 %type<decl> asm_name_opt 406 %type<e xpr> asm_operands_opt asm_operands_list asm_operand407 %type<label s> label_list408 %type<e xpr> asm_clobbers_list_opt409 %type< is_volatile> asm_volatile_opt410 %type<e xpr> handler_predicate_opt405 %type<en> asm_operands_opt asm_operands_list asm_operand 406 %type<label> label_list 407 %type<en> asm_clobbers_list_opt 408 %type<flag> asm_volatile_opt 409 %type<en> handler_predicate_opt 411 410 %type<genexpr> generic_association generic_assoc_list 412 411 413 412 // statements 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 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 430 428 %type<wfs> wor_waitfor_clause 431 %type<wu cn> waituntil_clause wand_waituntil_clause wor_waituntil_clause429 %type<wuscn> waituntil_clause wand_waituntil_clause wor_waituntil_clause 432 430 433 431 // declarations … … 441 439 %type<decl> assertion assertion_list assertion_list_opt 442 440 443 %type<e xpr> bit_subrange_size_opt bit_subrange_size441 %type<en> bit_subrange_size_opt bit_subrange_size 444 442 445 443 %type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type … … 454 452 455 453 %type<decl> enumerator_list enum_type enum_type_nobody 456 %type<in it> enumerator_value_opt454 %type<in> enumerator_value_opt 457 455 458 456 %type<decl> external_definition external_definition_list external_definition_list_opt … … 461 459 462 460 %type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract 463 %type<e xpr> field field_name_list field_name fraction_constants_opt461 %type<en> field field_name_list field_name fraction_constants_opt 464 462 465 463 %type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr … … 510 508 %type<decl> type_parameter type_parameter_list type_initializer_opt 511 509 512 %type<e xpr> type_parameters_opt type_list array_type_list510 %type<en> type_parameters_opt type_list array_type_list 513 511 514 512 %type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list … … 521 519 522 520 // initializers 523 %type<in it> initializer initializer_list_opt initializer_opt521 %type<in> initializer initializer_list_opt initializer_opt 524 522 525 523 // designators 526 %type<e xpr> designator designator_list designation524 %type<en> designator designator_list designation 527 525 528 526 … … 646 644 647 645 string_literal: 648 string_literal_list { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 )); }646 string_literal_list { $$ = build_constantStr( yylloc, *$1 ); } 649 647 ; 650 648 … … 741 739 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 742 740 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"] 743 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }741 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); } 744 742 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 745 743 { … … 759 757 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 760 758 | string_literal '`' identifier // CFA, postfix call 761 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1) ); }759 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), new ExpressionNode( $1 ) ) ); } 762 760 | postfix_expression '.' identifier 763 761 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } … … 859 857 | constant 860 858 | string_literal 861 { $$ = $1; }859 { $$ = new ExpressionNode( $1 ); } 862 860 | EXTENSION cast_expression // GCC 863 861 { $$ = $2->set_extension( true ); } … … 1262 1260 1263 1261 case_value_list: // CFA 1264 case_value { $$ = new ClauseNode( build_case( yylloc,$1 ) ); }1262 case_value { $$ = new StatementNode( build_case( $1 ) ); } 1265 1263 // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5" 1266 | case_value_list ',' case_value { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3) ) ); }1264 | case_value_list ',' case_value { $$ = (StatementNode *)($1->set_last( new StatementNode( build_case( $3 ) ) ) ); } 1267 1265 ; 1268 1266 … … 1273 1271 | CASE case_value_list error // syntax error 1274 1272 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; } 1275 | DEFAULT ':' { $$ = new ClauseNode( build_default( yylloc ) ); }1273 | DEFAULT ':' { $$ = new StatementNode( build_default( yylloc ) ); } 1276 1274 // A semantic check is required to ensure only one default clause per switch/choose statement. 1277 1275 | DEFAULT error // syntax error … … 1281 1279 case_label_list: // CFA 1282 1280 case_label 1283 | case_label_list case_label { $$ = $1->set_last( $2); }1281 | case_label_list case_label { $$ = (StatementNode *)( $1->set_last( $2 )); } 1284 1282 ; 1285 1283 … … 1298 1296 { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); } 1299 1297 | switch_clause_list case_label_list statement_list_nodecl 1300 { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3) ) ) ); }1298 { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ) ); } 1301 1299 ; 1302 1300 … … 1681 1679 1682 1680 waituntil: 1683 WAITUNTIL '(' c omma_expression ')'1681 WAITUNTIL '(' cast_expression ')' 1684 1682 { $$ = $3; } 1685 1683 ; … … 1738 1736 handler_clause: 1739 1737 handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1740 { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }1738 { $$ = new StatementNode( build_catch( yylloc, $1, $4, $6, $8 ) ); } 1741 1739 | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1742 { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }1740 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); } 1743 1741 ; 1744 1742 … … 1757 1755 1758 1756 finally_clause: 1759 FINALLY compound_statement { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); }1757 FINALLY compound_statement { $$ = new StatementNode( build_finally( yylloc, $2 ) ); } 1760 1758 ; 1761 1759 … … 1815 1813 asm_operand: // GCC 1816 1814 string_literal '(' constant_expression ')' 1817 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }1815 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", $1, maybeMoveBuild( $3 ) ) ); } 1818 1816 | '[' IDENTIFIER ']' string_literal '(' constant_expression ')' 1819 1817 { 1820 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) );1818 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, $4, maybeMoveBuild( $6 ) ) ); 1821 1819 delete $2.str; 1822 1820 } … … 1827 1825 { $$ = nullptr; } // use default argument 1828 1826 | string_literal 1829 { $$ = $1; }1827 { $$ = new ExpressionNode( $1 ); } 1830 1828 | asm_clobbers_list_opt ',' string_literal 1831 { $$ = (ExpressionNode *)( $1->set_last( $3 )); }1829 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( $3 ) )); } 1832 1830 ; 1833 1831 … … 1901 1899 static_assert: 1902 1900 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11 1903 { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 )); }1901 { $$ = DeclarationNode::newStaticAssert( $3, $5 ); } 1904 1902 | STATICASSERT '(' constant_expression ')' ';' // CFA 1905 1903 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); } … … 3331 3329 { 3332 3330 DeclarationNode * name = new DeclarationNode(); 3333 name->asmName = maybeMoveBuild( $3 );3331 name->asmName = $3; 3334 3332 $$ = name->addQualifiers( $5 ); 3335 3333 } -
src/Parser/parserutility.h
r6e1e2d0 ra50fdfb 24 24 25 25 template< typename T > 26 static inline auto maybeBuild( T *orig ) -> decltype(orig->build()) {26 static inline auto maybeBuild( const 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( T *orig ) -> decltype(orig->build()) {31 static inline auto maybeMoveBuild( const T *orig ) -> decltype(orig->build()) { 32 32 auto ret = maybeBuild<T>(orig); 33 33 delete orig; -
src/ResolvExpr/CandidateFinder.cpp
r6e1e2d0 ra50fdfb 55 55 namespace ResolvExpr { 56 56 57 /// Unique identifier for matching expression resolutions to their requesting expression58 UniqueId globalResnSlot = 0;59 60 namespace {61 /// First index is which argument, second is which alternative, third is which exploded element62 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;63 64 /// Returns a list of alternatives with the minimum cost in the given list65 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 type81 const ast::Expr * computeExpressionConversionCost(82 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost83 ) {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 requires89 // conversion. Ignore poly cost for now, since this requires resolution of the cast to90 // infer parameters and this does not currently work for the reason stated below91 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 not99 // 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* since103 // commontype(zero_t, DT*) is DT*, rather than nothing104 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 candidate118 Cost computeApplicationConversionCost(119 CandidateRef cand, const ast::SymbolTable & symtab120 ) {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 expressions145 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 system155 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 type162 // 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 continue169 }170 171 if ( param != params.end() ) return Cost::infinity;172 173 // specialization cost of return types can't be accounted for directly, it disables174 // 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 newline178 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization179 // }180 181 // mark type variable and specialization cost of forall clause182 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 & need191 ) {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 present201 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 arguments213 struct ArgPack {214 std::size_t parent; ///< Index of parent pack215 ast::ptr< ast::Expr > expr; ///< The argument stored here216 Cost cost; ///< The cost of this argument217 ast::TypeEnvironment env; ///< Environment for this pack218 ast::AssertionSet need; ///< Assertions outstanding for this pack219 ast::AssertionSet have; ///< Assertions found for this pack220 ast::OpenVarSet open; ///< Open variables for this pack221 unsigned nextArg; ///< Index of next argument in arguments list222 unsigned tupleStart; ///< Number of tuples that start at this index223 unsigned nextExpl; ///< Index of next exploded element224 unsigned explAlt; ///< Index of alternative for nextExpl > 0225 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 argument253 bool hasExpl() const { return nextExpl > 0; }254 255 /// Gets the list of exploded candidates for this pack256 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const {257 return args[ nextArg-1 ][ explAlt ];258 }259 260 /// Ends a tuple expression, consolidating the appropriate args261 void endTuple( const std::vector< ArgPack > & packs ) {262 // add all expressions in tuple to list, summing cost263 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 tuple272 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 left280 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 = 0285 ) {286 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {287 // paramType is a TupleType -- group args into a TupleExpr288 ++nTuples;289 for ( const ast::Type * type : *tupleType ) {290 // xxx - dropping initializer changes behaviour from previous, but seems correct291 // ^^^ need to handle the case where a tuple has a default argument292 if ( ! instantiateArgument( location,293 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;294 nTuples = 0;295 }296 // re-constitute tuples for final generation297 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 arguments303 304 // completed tuples; will be spliced to end of results to finish305 std::vector< ArgPack > finalResults{};306 307 // iterate until all results completed308 std::size_t genEnd;309 ++nTuples;310 do {311 genEnd = results.size();312 313 // add another argument to results314 for ( std::size_t i = genStart; i < genEnd; ++i ) {315 unsigned nextArg = results[i].nextArg;316 317 // use next element of exploded tuple if present318 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 arguments334 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 expression343 newResult.parent = i;344 newResult.expr = new ast::TupleExpr( location, {} );345 argType = newResult.expr->result;346 } else {347 // clone result to collect tuple348 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 purposes357 // xxx - what if passing multiple arguments, last of which is358 // ttype?359 // xxx - what would happen if unify was changed so that unifying360 // tuple361 // types flattened both before unifying lists? then pass in362 // TupleType (ttype) below.363 --newResult.tupleStart;364 } else {365 // collapse leftover arguments into tuple366 newResult.endTuple( results );367 argType = newResult.expr->result;368 }369 }370 371 // check unification for ttype before adding to final372 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 argument384 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 iteration388 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 gen394 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 result403 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 round411 genStart = genEnd;412 nTuples = 0;413 } while ( genEnd != results.size() );414 415 // splice final results onto results416 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 subresult423 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 present428 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 arguments459 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 argument476 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 iteration480 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 gen487 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 arg496 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 types508 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {509 // add new result510 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 parameter518 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::GeneratedCast526 ) {527 if (528 arg->result->size() > 1529 && ! 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 each533 // member of the tuple to its corresponding target type, producing the tuple of those534 // cast expressions. If there are more components of the tuple than components in the535 // target type, then excess components do not come out in the result expression (but536 // 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 of539 // the expression540 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 component545 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 normally552 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 interpretations566 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 NoReason584 };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 list597 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 inference608 void inferParameters( CandidateRef & newCand, CandidateList & out );609 610 /// Completes a function candidate with arguments located611 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 out616 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 list622 void addAnonConversions( const CandidateRef & cand );623 624 /// Adds aggregate member interpretations625 void addAggMembers(626 const ast::BaseInstType * aggrInst, const ast::Expr * expr,627 const Candidate & cand, const Cost & addedCost, const std::string & name628 );629 630 /// Adds tuple member interpretations631 void addTupleMembers(632 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,633 const Cost & addedCost, const ast::Expr * member634 );635 636 /// true if expression is an lvalue637 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 inference685 void Finder::inferParameters( CandidateRef & newCand, CandidateList & out ) {686 // Set need bindings for any unbound assertions687 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions688 for ( auto & assn : newCand->need ) {689 // skip already-matched assertions690 if ( assn.second.resnSlot != 0 ) continue;691 // assign slot for expression if needed692 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }693 // fix slot to assertion694 assn.second.resnSlot = crntResnSlot;695 }696 // pair slot to expression697 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 later702 out.emplace_back( newCand );703 }704 705 /// Completes a function candidate with arguments located706 void Finder::validateFunctionCandidate(707 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,708 CandidateList & out709 ) {710 ast::ApplicationExpr * appExpr =711 new ast::ApplicationExpr{ func->expr->location, func->expr };712 // sum cost and accumulate arguments713 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 candidate724 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 out735 void Finder::makeFunctionCandidates(736 const CodeLocation & location,737 const CandidateRef & func, const ast::FunctionType * funcType,738 const ExplodedArgs_new & args, CandidateList & out739 ) {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 the745 // parameter list are still considered open746 funcEnv.add( funcType->forall );747 748 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {749 // attempt to narrow based on expected target type750 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 candidate755 return;756 }757 }758 759 // iteratively build matches, one parameter at a time760 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 name768 // must use types on candidate however, due to RenameVars substitution769 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 existing781 // matches782 // no default args for indirect calls783 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 pack790 std::size_t genEnd;791 do {792 genEnd = results.size();793 794 // iterate results795 for ( std::size_t i = genStart; i < genEnd; ++i ) {796 unsigned nextArg = results[i].nextArg;797 798 // use remainder of exploded tuple if present799 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 arguments815 if ( nextArg >= args.size() ) {816 validateFunctionCandidate( func, results[i], results, out );817 818 continue;819 }820 821 // add each possible next argument822 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 iteration826 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 gen832 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 result842 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 arguments853 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 list863 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 the866 // base type to treat the aggregate as the referenced value867 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 interpretations883 void Finder::addAggMembers(884 const ast::BaseInstType * aggrInst, const ast::Expr * expr,885 const Candidate & cand, const Cost & addedCost, const std::string & name886 ) {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 seen892 // as a member expression893 addAnonConversions( newCand );894 candidates.emplace_back( std::move( newCand ) );895 }896 }897 898 /// Adds tuple member interpretations899 void Finder::addTupleMembers(900 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,901 const Cost & addedCost, const ast::Expr * member902 ) {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 the905 // length of the tuple to have meaning906 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 assignments920 // if not tuple assignment, handled as normal function call921 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 references932 // xxx - is this correct?933 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base;934 935 // convert 1-tuple to plain type936 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; // Here951 // 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 int956 // 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 fail964 // 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, // adjust968 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name969 selfFinder.candidates.empty() // failfast if other options are not found970 };971 funcFinder.find( untypedExpr->func, mode );972 // short-circuit if no candidates973 // if ( funcFinder.candidates.empty() ) return;974 975 reason.code = NoMatch;976 977 // find function operators978 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 operations981 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 arguments988 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 matches996 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 function1006 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 list1034 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-function1044 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-error1059 // candidates1060 if ( found.empty() && ! errors.isEmpty() ) { throw errors; }1061 1062 // Compute conversion costs1063 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 twice1090 CandidateList winners = findMinCost( found );1091 promoteCvtCost( winners );1092 1093 // function may return a struct/union value, in which case we need to add candidates1094 // for implicit conversions to each of the anonymous members, which must happen after1095 // `findMinCost`, since anon conversions are never the cheapest1096 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 it1103 // 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 char1110 // * (x: const char *) is unified with unsigned char *, which fails1111 // xxx -- fix this better1112 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-valued1154 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the1155 // subexpression results that are cast directly. The candidate is invalid if it1156 // 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-effects1161 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 away1177 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 cost1187 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 type1196 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.__thrd1239 // Clone is purely for memory management1240 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 type1243 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 type1252 finder.find( fallback.get(), ResolvMode::withoutPrune() );1253 1254 pick_alternatives(finder.candidates, true);1255 1256 // Whatever happens here, we have no more fallbacks1257 }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 the1264 // base type to treat the aggregate as the referenced value1265 Cost addedCost = Cost::zero;1266 agg->expr = referenceToRvalueConversion( agg->expr, addedCost );1267 1268 // find member of the given type1269 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 seen1331 // as a name expression1332 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 since1339 // creation1340 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 sizeof1356 CandidateFinder finder( context, tenv );1357 finder.find( sizeofExpr->expr );1358 // find the lowest-cost candidate, otherwise ambiguous1359 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 candidate1365 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 alignof1380 CandidateFinder finder( context, tenv );1381 finder.find( alignofExpr->expr );1382 // find the lowest-cost candidate, otherwise ambiguous1383 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 candidate1389 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 condition1449 CandidateFinder finder1( context, tenv );1450 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );1451 if ( finder1.candidates.empty() ) return;1452 1453 // candidates for true result1454 CandidateFinder finder2( context, tenv );1455 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );1456 if ( finder2.candidates.empty() ) return;1457 1458 // candidates for false result1459 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 new1481 // candidates1482 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 expression1489 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 type1493 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 candidate1499 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 unify1534 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 expression1562 ast::RangeExpr * newExpr =1563 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };1564 newExpr->result = common ? common : r1->expr->result;1565 // add candidate1566 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 cast1628 CandidateList matches;1629 PRINT(1630 std::cerr << "untyped init expr: " << initExpr << std::endl;1631 )1632 // O(n^2) checks of d-types with e-types1633 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {1634 // calculate target type1635 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 return1638 // types are not bound to the initialization type, since return type variables are1639 // 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-valued1654 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of1655 // the subexpression results that are cast directly. The candidate is invalid1656 // 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-effects1661 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 away1678 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 cost1690 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 given1697 /// return type. Skips ambiguous candidates.1698 1699 } // anonymous namespace1700 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 type1711 std::unordered_map< std::string, PruneStruct > selected;1712 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found1713 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 contains1734 // unbound type parameters, then it should never be pruned by1735 // the previous step, since renameTyVars guarantees the mangled name1736 // 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 it1749 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 option1768 // that is at least as good1769 if ( findDeletedExpr( newCand->expr ) ) {1770 // do nothing1771 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 candidates1793 // 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 error1807 return !selected.empty();1808 }1809 1810 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {1811 // Find alternatives for expression1812 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 satisfiable1834 // - necessary pre-requisite to pruning1835 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 such1842 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 candidates1852 candidates = move( satisfied );1853 }1854 */1855 1856 if ( mode.prune ) {1857 // trim candidates to single best one1858 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 correctly1900 // adjusted1901 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 expressions1910 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 > > & xs1919 ) {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 1935 57 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) { 1936 58 if ( expr->result.as< ast::ReferenceType >() ) { … … 1942 64 return expr; 1943 65 } 66 67 /// Unique identifier for matching expression resolutions to their requesting expression 68 UniqueId globalResnSlot = 0; 1944 69 1945 70 Cost computeConversionCost( … … 1968 93 } 1969 94 95 namespace { 96 /// First index is which argument, second is which alternative, third is which exploded element 97 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >; 98 99 /// Returns a list of alternatives with the minimum cost in the given list 100 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 type 116 const ast::Expr * computeExpressionConversionCost( 117 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 118 ) { 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 requires 124 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 125 // infer parameters and this does not currently work for the reason stated below 126 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 not 134 // 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* since 138 // commontype(zero_t, DT*) is DT*, rather than nothing 139 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 candidate 153 Cost computeApplicationConversionCost( 154 CandidateRef cand, const ast::SymbolTable & symtab 155 ) { 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 expressions 180 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 system 190 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 type 197 // 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 continue 204 } 205 206 if ( param != params.end() ) return Cost::infinity; 207 208 // specialization cost of return types can't be accounted for directly, it disables 209 // 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 newline 213 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 214 // } 215 216 // mark type variable and specialization cost of forall clause 217 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 & need 226 ) { 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 present 236 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 arguments 248 struct ArgPack { 249 std::size_t parent; ///< Index of parent pack 250 ast::ptr< ast::Expr > expr; ///< The argument stored here 251 Cost cost; ///< The cost of this argument 252 ast::TypeEnvironment env; ///< Environment for this pack 253 ast::AssertionSet need; ///< Assertions outstanding for this pack 254 ast::AssertionSet have; ///< Assertions found for this pack 255 ast::OpenVarSet open; ///< Open variables for this pack 256 unsigned nextArg; ///< Index of next argument in arguments list 257 unsigned tupleStart; ///< Number of tuples that start at this index 258 unsigned nextExpl; ///< Index of next exploded element 259 unsigned explAlt; ///< Index of alternative for nextExpl > 0 260 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 argument 288 bool hasExpl() const { return nextExpl > 0; } 289 290 /// Gets the list of exploded candidates for this pack 291 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const { 292 return args[ nextArg-1 ][ explAlt ]; 293 } 294 295 /// Ends a tuple expression, consolidating the appropriate args 296 void endTuple( const std::vector< ArgPack > & packs ) { 297 // add all expressions in tuple to list, summing cost 298 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 tuple 307 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 left 315 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 = 0 319 ) { 320 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { 321 // paramType is a TupleType -- group args into a TupleExpr 322 ++nTuples; 323 for ( const ast::Type * type : *tupleType ) { 324 // xxx - dropping initializer changes behaviour from previous, but seems correct 325 // ^^^ need to handle the case where a tuple has a default argument 326 if ( ! instantiateArgument( 327 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 328 nTuples = 0; 329 } 330 // re-constitute tuples for final generation 331 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 arguments 337 338 // completed tuples; will be spliced to end of results to finish 339 std::vector< ArgPack > finalResults{}; 340 341 // iterate until all results completed 342 std::size_t genEnd; 343 ++nTuples; 344 do { 345 genEnd = results.size(); 346 347 // add another argument to results 348 for ( std::size_t i = genStart; i < genEnd; ++i ) { 349 unsigned nextArg = results[i].nextArg; 350 351 // use next element of exploded tuple if present 352 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 arguments 368 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 expression 377 newResult.parent = i; 378 newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} }; 379 argType = newResult.expr->result; 380 } else { 381 // clone result to collect tuple 382 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 purposes 391 // xxx - what if passing multiple arguments, last of which is 392 // ttype? 393 // xxx - what would happen if unify was changed so that unifying 394 // tuple 395 // types flattened both before unifying lists? then pass in 396 // TupleType (ttype) below. 397 --newResult.tupleStart; 398 } else { 399 // collapse leftover arguments into tuple 400 newResult.endTuple( results ); 401 argType = newResult.expr->result; 402 } 403 } 404 405 // check unification for ttype before adding to final 406 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 argument 418 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 iteration 422 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 gen 428 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 result 437 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 round 445 genStart = genEnd; 446 nTuples = 0; 447 } while ( genEnd != results.size() ); 448 449 // splice final results onto results 450 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 subresult 457 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 present 462 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 arguments 493 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 argument 510 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 iteration 514 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 gen 521 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 arg 530 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 types 542 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 543 // add new result 544 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 parameter 552 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::GeneratedCast 560 ) { 561 if ( 562 arg->result->size() > 1 563 && ! 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 each 567 // member of the tuple to its corresponding target type, producing the tuple of those 568 // cast expressions. If there are more components of the tuple than components in the 569 // target type, then excess components do not come out in the result expression (but 570 // 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 of 573 // the expression 574 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 component 579 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 normally 586 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 interpretations 600 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 NoReason 618 }; 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 list 631 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 inference 642 void inferParameters( CandidateRef & newCand, CandidateList & out ) { 643 // Set need bindings for any unbound assertions 644 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 645 for ( auto & assn : newCand->need ) { 646 // skip already-matched assertions 647 if ( assn.second.resnSlot != 0 ) continue; 648 // assign slot for expression if needed 649 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 650 // fix slot to assertion 651 assn.second.resnSlot = crntResnSlot; 652 } 653 // pair slot to expression 654 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 later 659 out.emplace_back( newCand ); 660 } 661 662 /// Completes a function candidate with arguments located 663 void validateFunctionCandidate( 664 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 665 CandidateList & out 666 ) { 667 ast::ApplicationExpr * appExpr = 668 new ast::ApplicationExpr{ func->expr->location, func->expr }; 669 // sum cost and accumulate arguments 670 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 candidate 681 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 out 692 void makeFunctionCandidates( 693 const CandidateRef & func, const ast::FunctionType * funcType, 694 const ExplodedArgs_new & args, CandidateList & out 695 ) { 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 the 701 // parameter list are still considered open 702 funcEnv.add( funcType->forall ); 703 704 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) { 705 // attempt to narrow based on expected target type 706 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 candidate 711 return; 712 } 713 } 714 715 // iteratively build matches, one parameter at a time 716 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 name 724 // must use types on candidate however, due to RenameVars substitution 725 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 existing 737 // matches 738 // no default args for indirect calls 739 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 pack 746 std::size_t genEnd; 747 do { 748 genEnd = results.size(); 749 750 // iterate results 751 for ( std::size_t i = genStart; i < genEnd; ++i ) { 752 unsigned nextArg = results[i].nextArg; 753 754 // use remainder of exploded tuple if present 755 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 arguments 771 if ( nextArg >= args.size() ) { 772 validateFunctionCandidate( func, results[i], results, out ); 773 774 continue; 775 } 776 777 // add each possible next argument 778 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 iteration 782 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 gen 788 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 result 798 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 arguments 809 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 list 819 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 the 822 // base type to treat the aggregate as the referenced value 823 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 interpretations 839 void addAggMembers( 840 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 841 const Candidate & cand, const Cost & addedCost, const std::string & name 842 ) { 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 seen 848 // as a member expression 849 addAnonConversions( newCand ); 850 candidates.emplace_back( std::move( newCand ) ); 851 } 852 } 853 854 /// Adds tuple member interpretations 855 void addTupleMembers( 856 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 857 const Cost & addedCost, const ast::Expr * member 858 ) { 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 the 861 // length of the tuple to have meaning 862 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 assignments 876 // if not tuple assignment, handled as normal function call 877 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 references 888 // xxx - is this correct? 889 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base; 890 891 // convert 1-tuple to plain type 892 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; // Here 907 // 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 int 912 // 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 fail 920 // 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, // adjust 924 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name 925 selfFinder.candidates.empty() // failfast if other options are not found 926 }; 927 funcFinder.find( untypedExpr->func, mode ); 928 // short-circuit if no candidates 929 // if ( funcFinder.candidates.empty() ) return; 930 931 reason.code = NoMatch; 932 933 // find function operators 934 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 operations 937 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 arguments 944 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 matches 952 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 function 962 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 list 988 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-function 998 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-error 1012 // candidates 1013 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } 1014 1015 // Compute conversion costs 1016 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 twice 1043 CandidateList winners = findMinCost( found ); 1044 promoteCvtCost( winners ); 1045 1046 // function may return a struct/union value, in which case we need to add candidates 1047 // for implicit conversions to each of the anonymous members, which must happen after 1048 // `findMinCost`, since anon conversions are never the cheapest 1049 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 it 1056 // 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 char 1063 // * (x: const char *) is unified with unsigned char *, which fails 1064 // xxx -- fix this better 1065 targetType = nullptr; 1066 postvisit( untypedExpr ); 1067 } 1068 } 1069 1070 /// true if expression is an lvalue 1071 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-valued 1112 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1113 // subexpression results that are cast directly. The candidate is invalid if it 1114 // 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-effects 1119 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 away 1135 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 cost 1145 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 type 1154 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.__thrd 1197 // Clone is purely for memory management 1198 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 type 1201 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 type 1210 finder.find( fallback.get(), ResolvMode::withoutPrune() ); 1211 1212 pick_alternatives(finder.candidates, true); 1213 1214 // Whatever happens here, we have no more fallbacks 1215 } 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 the 1222 // base type to treat the aggregate as the referenced value 1223 Cost addedCost = Cost::zero; 1224 agg->expr = referenceToRvalueConversion( agg->expr, addedCost ); 1225 1226 // find member of the given type 1227 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 seen 1290 // as a name expression 1291 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 since 1298 // creation 1299 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 sizeof 1315 CandidateFinder finder( context, tenv ); 1316 finder.find( sizeofExpr->expr ); 1317 // find the lowest-cost candidate, otherwise ambiguous 1318 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 candidate 1324 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 alignof 1339 CandidateFinder finder( context, tenv ); 1340 finder.find( alignofExpr->expr ); 1341 // find the lowest-cost candidate, otherwise ambiguous 1342 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 candidate 1348 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 condition 1408 CandidateFinder finder1( context, tenv ); 1409 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() ); 1410 if ( finder1.candidates.empty() ) return; 1411 1412 // candidates for true result 1413 CandidateFinder finder2( context, tenv ); 1414 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1415 if ( finder2.candidates.empty() ) return; 1416 1417 // candidates for false result 1418 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 new 1440 // candidates 1441 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 expression 1448 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 type 1452 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 candidate 1458 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 unify 1493 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 expression 1521 ast::RangeExpr * newExpr = 1522 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1523 newExpr->result = common ? common : r1->expr->result; 1524 // add candidate 1525 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 cast 1587 CandidateList matches; 1588 PRINT( 1589 std::cerr << "untyped init expr: " << initExpr << std::endl; 1590 ) 1591 // O(n^2) checks of d-types with e-types 1592 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) { 1593 // calculate target type 1594 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 return 1597 // types are not bound to the initialization type, since return type variables are 1598 // 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-valued 1613 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1614 // the subexpression results that are cast directly. The candidate is invalid 1615 // 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-effects 1620 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 away 1637 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 cost 1650 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 given 1670 /// return type. Skips ambiguous candidates. 1671 1672 } // anonymous namespace 1673 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 type 1684 std::unordered_map< std::string, PruneStruct > selected; 1685 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found 1686 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 contains 1707 // unbound type parameters, then it should never be pruned by 1708 // the previous step, since renameTyVars guarantees the mangled name 1709 // 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 it 1722 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 option 1741 // that is at least as good 1742 if ( findDeletedExpr( newCand->expr ) ) { 1743 // do nothing 1744 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 candidates 1766 // 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 error 1780 return !selected.empty(); 1781 } 1782 1783 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) { 1784 // Find alternatives for expression 1785 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 satisfiable 1807 // - necessary pre-requisite to pruning 1808 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 such 1815 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 candidates 1825 candidates = move( satisfied ); 1826 } 1827 */ 1828 1829 if ( mode.prune ) { 1830 // trim candidates to single best one 1831 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 correctly 1873 // adjusted 1874 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 expressions 1883 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 > > & xs 1892 ) { 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 1970 1908 } // namespace ResolvExpr 1971 1909 -
src/ResolvExpr/CurrentObject.cc
r6e1e2d0 ra50fdfb 9 9 // Author : Rob Schluntz 10 10 // Created On : Tue Jun 13 15:28:32 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Mon Apr 10 9:40:00 202313 // Update Count : 1 811 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 1 09:16:01 2022 13 // Update Count : 15 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 the611 /// 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 init630 /// alternative, but adding designators in operator* creates duplicates.631 virtual std::deque< InitAlternative > first() const = 0;632 };633 634 595 /// create a new MemberIterator that traverses a type correctly 635 596 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ); … … 671 632 }; 672 633 673 /// Iterates over an indexed type: 674 class IndexIterator : public MemberIterator { 675 protected: 634 /// Iterates array types 635 class ArrayIterator final : public MemberIterator { 676 636 CodeLocation location; 637 const ArrayType * array = nullptr; 638 const Type * base = nullptr; 677 639 size_t index = 0; 678 640 size_t size = 0; 679 std::unique_ptr<MemberIterator> memberIter; 680 public: 681 IndexIterator( const CodeLocation & loc, size_t size ) : 682 location( loc ), size( size ) 683 {} 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 } 684 660 685 661 void setPosition( const Expr * expr ) { … … 690 666 auto arg = eval( expr ); 691 667 index = arg.first; 668 return; 692 669 693 670 // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { … … 707 684 708 685 void setPosition( 709 std::deque< ast::ptr<ast::Expr>>::const_iterator begin,710 std::deque< ast::ptr<ast::Expr>>::const_iterator end686 std::deque< ptr< Expr > >::const_iterator begin, 687 std::deque< ptr< Expr > >::const_iterator end 711 688 ) override { 712 689 if ( begin == end ) return; … … 719 696 720 697 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 }746 698 747 699 ArrayIterator & bigStep() override { … … 882 834 883 835 const Type * getNext() final { 884 bool hasMember = memberIter && *memberIter; 885 return hasMember ? memberIter->getType() : nullptr; 836 return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr; 886 837 } 887 838 … … 947 898 }; 948 899 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() ) ); 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); 963 909 } 964 910 965 911 TupleIterator & bigStep() override { 966 ++index; 967 memberIter.reset( index < size ? 968 createMemberIterator( location, typeAtIndex() ) : nullptr ); 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 } 969 920 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 {};1004 921 } 1005 922 }; -
src/ResolvExpr/CurrentObject.h
r6e1e2d0 ra50fdfb 9 9 // Author : Rob Schluntz 10 10 // Created On : Thu Jun 8 11:07:25 2017 11 // Last Modified By : Andrew Beach12 // Last Modified On : Thu Apr 6 16:14:00 202313 // Update Count : 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:36:48 2017 13 // Update Count : 3 14 14 // 15 15 … … 65 65 66 66 /// Iterates members of a type by initializer 67 class MemberIterator; 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 }; 68 104 69 105 /// Builds initializer lists in resolution -
src/ResolvExpr/ExplodedArg.hpp
r6e1e2d0 ra50fdfb 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
r6e1e2d0 ra50fdfb 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 14 15:03:00 202313 // Update Count : 6 412 // Last Modified On : Fri Apr 27 14:39:06 2018 13 // Update Count : 63 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 213 217 /// inserts a forward declaration for functionDecl into declsToAdd 214 218 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { … … 230 234 } 231 235 236 // shallow copy the pointer list for return 237 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 232 247 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 233 248 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { … … 241 256 ftype->parameters.push_back( dstParam ); 242 257 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); 243 266 } 244 267 -
src/SymTab/Autogen.h
r6e1e2d0 ra50fdfb 9 9 // Author : Rob Schluntz 10 10 // Created On : Sun May 17 21:53:34 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Fri Apr 14 15:06:00 202313 // Update Count : 1 711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 13 16:38:06 2019 13 // Update Count : 16 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 ); 47 48 48 49 /// generate the type of an assignment function for paramType. … … 54 55 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true ); 55 56 57 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true); 58 56 59 /// generate the type of a copy constructor for paramType. 57 60 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic … … 64 67 template< typename OutputIterator > 65 68 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 ); 66 75 67 76 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. … … 112 121 113 122 *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 and 130 /// srcParam. Should only be called with non-array types. 131 /// optionally returns a statement which must be inserted prior to the containing loop, if 132 /// there is one 133 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 = nullptr 138 ) { 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 cast 143 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 of 150 // "?=?", "?{}", 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 and 155 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue 156 // is considered a qualifier - for AddressExpr to resolve, its argument must have an 157 // 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 addCast 160 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 arguments 171 ++srcParam; 172 173 // return if adding reference fails -- will happen on default ctor and dtor 174 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 }; 114 180 115 181 srcParam.clearArrayIndices(); … … 182 248 } 183 249 250 /// Store in out a loop which calls fname on each element of the array with srcParam and 251 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0 252 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 = LoopForward 258 ) { 259 static UniqueName indexName( "_index" ); 260 261 // for a flexible array member nothing is done -- user must define own assignment 262 if ( ! array->dimension ) return; 263 264 if ( addCast ) { 265 // peel off array layer from cast 266 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/or 302 // array list initializer 303 srcParam.addArrayIndex( indexVar, array->dimension ); 304 305 // for stmt's body, eventually containing call 306 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 variable 312 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 184 320 template< typename OutputIterator > 185 321 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) { … … 189 325 } else { 190 326 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 forward 335 ) { 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 ); 191 344 } 192 345 } … … 226 379 } 227 380 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 = LoopForward 385 ) { 386 // unnamed bit fields are not copied as they cannot be accessed 387 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 are 405 // 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 } 228 414 } // namespace SymTab 229 415 -
src/SymTab/module.mk
r6e1e2d0 ra50fdfb 20 20 SymTab/FixFunction.cc \ 21 21 SymTab/FixFunction.h \ 22 SymTab/GenImplicitCall.cpp \23 SymTab/GenImplicitCall.hpp \24 22 SymTab/Indexer.cc \ 25 23 SymTab/Indexer.h \ -
src/Validate/Autogen.cpp
r6e1e2d0 ra50fdfb 39 39 #include "InitTweak/GenInit.h" // for fixReturnStatements 40 40 #include "InitTweak/InitTweak.h" // for isAssignment, isCopyConstructor 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall42 41 #include "SymTab/Mangler.h" // for Mangler 43 42 #include "CompilationState.h" … … 424 423 for ( unsigned int index = 0 ; index < fields ; ++index ) { 425 424 auto member = aggr->members[index].strict_as<ast::DeclWithType>(); 426 if ( ast::isUnnamedBitfield(425 if ( SymTab::isUnnamedBitfield( 427 426 dynamic_cast<const ast::ObjectDecl *>( member ) ) ) { 428 427 if ( index == fields - 1 ) { … … 600 599 // Not sure why it could be null. 601 600 // Don't make a function for a parameter that is an unnamed bitfield. 602 if ( nullptr == field || ast::isUnnamedBitfield( field ) ) {601 if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) { 603 602 continue; 604 603 // Matching Parameter: Initialize the field by copy. -
src/main.cc
r6e1e2d0 ra50fdfb 9 9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Apr 10 21:12:17202313 // Update Count : 68 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Feb 16 10:08:00 2023 13 // Update Count : 680 14 14 // 15 15 … … 32 32 33 33 #include "AST/Convert.hpp" 34 #include "AST/Util.hpp" // for checkInvariants35 34 #include "CompilationState.h" 36 35 #include "../config.h" // for CFA_LIBDIR … … 103 102 } 104 103 105 // Helpers for checkInvariant: 106 void checkInvariants( std::list< Declaration * > & ) {} 107 using ast::checkInvariants; 108 109 #define PASS( name, pass, unit, ... ) \ 104 #define PASS( name, pass ) \ 110 105 if ( errorp ) { cerr << name << endl; } \ 111 106 NewPass(name); \ 112 107 Stats::Time::StartBlock(name); \ 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 } 108 pass; \ 109 Stats::Time::StopBlock(); 124 110 125 111 static bool waiting_for_gdb = false; // flag to set cfa-cpp to wait for gdb on start … … 312 298 transUnit = buildUnit(); 313 299 314 DUMP( astp, std::move( transUnit ) ); 300 if ( astp ) { 301 dump( std::move( transUnit ) ); 302 return EXIT_SUCCESS; 303 } // if 315 304 316 305 Stats::Time::StopBlock(); … … 321 310 } 322 311 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 ); 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 ) ); 356 353 357 354 if ( symtabp ) { … … 364 361 } // if 365 362 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 ); 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 ) ); 373 373 374 374 if ( libcfap ) { … … 382 382 } // if 383 383 384 DUMP( bresolvep, std::move( transUnit ) ); 384 if ( bresolvep ) { 385 dump( std::move( transUnit ) ); 386 return EXIT_SUCCESS; 387 } // if 385 388 386 389 if ( resolvprotop ) { … … 389 392 } // if 390 393 391 PASS( "Resolve", ResolvExpr::resolve, transUnit ); 392 DUMP( exprp, std::move( transUnit ) ); 393 394 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); 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())); 395 403 396 404 // fix ObjectDecl - replaces ConstructorInit nodes 397 DUMP( ctorinitp, std::move( transUnit ) ); 405 if ( ctorinitp ) { 406 dump( std::move( transUnit ) ); 407 return EXIT_SUCCESS; 408 } // if 398 409 399 410 // Currently not working due to unresolved issues with UniqueExpr 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 reused401 402 PASS( "Translate Tries", ControlStruct::translateTries , transUnit);403 PASS( "Gen Waitfor", Concurrency::generateWaitFor , transUnit);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 reused 412 413 PASS( "Translate Tries", ControlStruct::translateTries( transUnit ) ); 414 PASS( "Gen Waitfor", Concurrency::generateWaitFor( transUnit ) ); 404 415 405 416 // Needs to happen before tuple types are expanded. 406 PASS( "Convert Specializations", GenPoly::convertSpecializations, transUnit ); 407 408 PASS( "Expand Tuples", Tuples::expandTuples, transUnit ); 409 DUMP( tuplep, std::move( transUnit ) ); 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 410 425 411 426 // Must come after Translate Tries. 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 ); 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 ) ); 418 436 419 437 translationUnit = convert( std::move( transUnit ) ); 420 438 421 DUMP( bboxp, translationUnit ); 422 PASS( "Box", GenPoly::box, translationUnit ); 423 424 PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit ); 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 ) ); 425 446 426 447 // Code has been lowered to C, now we can start generation. 427 448 428 DUMP( bcodegenp, translationUnit ); 449 if ( bcodegenp ) { 450 dump( translationUnit ); 451 return EXIT_SUCCESS; 452 } // if 429 453 430 454 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 433 457 434 458 CodeTools::fillLocations( translationUnit ); 435 PASS( "Code Gen", CodeGen::generate , translationUnit, *output, ! genproto, prettycodegenp, true, linemarks);459 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) ); 436 460 437 461 CodeGen::FixMain::fix( translationUnit, *output, … … 481 505 482 506 483 static const char optstring[] = ":c:gh ilLmNnpdP:S:twW:D:";507 static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:"; 484 508 485 509 enum { PreludeDir = 128 }; … … 488 512 { "gdb", no_argument, nullptr, 'g' }, 489 513 { "help", no_argument, nullptr, 'h' }, 490 { "invariant", no_argument, nullptr, 'i' },491 514 { "libcfa", no_argument, nullptr, 'l' }, 492 515 { "linemarks", no_argument, nullptr, 'L' }, 493 { "no-main", no_argument, nullptr, 'm' },516 { "no-main", no_argument, 0, 'm' }, 494 517 { "no-linemarks", no_argument, nullptr, 'N' }, 495 518 { "no-prelude", no_argument, nullptr, 'n' }, … … 510 533 "wait for gdb to attach", // -g 511 534 "print translator help message", // -h 512 "invariant checking during AST passes", // -i513 535 "generate libcfa.c", // -l 514 536 "generate line marks", // -L … … 604 626 usage( argv ); // no return 605 627 break; 606 case 'i': // invariant checking607 invariant = true;608 break;609 628 case 'l': // generate libcfa.c 610 629 libcfap = true; -
tests/.expect/PRNG.x64.txt
r6e1e2d0 ra50fdfb 1 2 CFA xoshiro256pp3 1 4 2 PRNG() PRNG(5) PRNG(0,5) … … 58 56 59 57 Sequential 60 trials 20000000 buckets 100000 min 139 max 265 avg 200.0 std 14.1 rstd 7.0%58 trials 100000000 buckets 100000 min 875 max 1146 avg 1000.0 std 31.6 rstd 3.2% 61 59 62 60 Concurrent 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%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% 67 65 68 66 prng(t) prng(t,5) prng(t,0,5) -
tests/.expect/PRNG.x86.txt
r6e1e2d0 ra50fdfb 1 2 CFA xoshiro128pp3 1 4 2 PRNG() PRNG(5) PRNG(0,5) … … 58 56 59 57 Sequential 60 trials 20000000 buckets 100000 min 144 max 270 avg 200.0 std 14.1 rstd 7.1%58 trials 100000000 buckets 100000 min 858 max 1147 avg 1000.0 std 31.5 rstd 3.2% 61 59 62 60 Concurrent 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%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% 67 65 68 66 prng(t) prng(t,5) prng(t,0,5) -
tests/Makefile.am
r6e1e2d0 ra50fdfb 11 11 ## Created On : Sun May 31 09:08:15 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Mon Apr 10 23:24:02202314 ## Update Count : 9 613 ## Last Modified On : Fri Feb 3 23:06:44 2023 14 ## Update Count : 94 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 concurrent/waitfor/parse186 init1 limits nested-types cast labelledExit array quasiKeyword include/stdincludes include/includes builtins/sync warnings/self-assignment 187 187 $(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN) 188 188 $(CFACOMPILE_SYNTAX) -
tests/PRNG.cfa
r6e1e2d0 ra50fdfb 8 8 // Created On : Wed Dec 29 09:38:12 2021 9 9 // Last Modified By : Peter A. Buhr 10 // Last Modified On : Sun Apr 23 22:02:09 202311 // Update Count : 4 2010 // Last Modified On : Wed Dec 21 20:39:59 2022 11 // Update Count : 406 12 12 // 13 13 … … 15 15 #include <stdlib.hfa> // PRNG 16 16 #include <clock.hfa> 17 #include <thread.hfa> 17 18 #include <limits.hfa> // MAX 18 19 #include <math.hfa> // sqrt 19 20 #include <malloc.h> // malloc_stats 20 21 #include <locale.h> // setlocale 21 #include <thread.hfa>22 22 #include <mutex_stmt.hfa> 23 23 24 #define xstr(s) str(s) 25 #define str(s) #s 26 27 #if defined( __x86_64__ ) || defined( __aarch64__ ) // 64-bit architecture 24 #ifdef __x86_64__ // 64-bit architecture 28 25 #define PRNG PRNG64 29 26 #else // 32-bit architecture 30 27 #define PRNG PRNG32 31 28 #endif // __x86_64__ 32 33 //#define TIME34 29 35 30 #ifdef TIME // use -O2 -nodebug … … 43 38 #endif // TIME 44 39 45 static void avgstd( size_t trials, size_t buckets[] ) {46 size_t min = MAX, max = 0;40 void avgstd( unsigned int buckets[] ) { 41 unsigned int min = MAX, max = 0; 47 42 double sum = 0.0, diff; 48 43 for ( i; BUCKETS ) { … … 59 54 } // for 60 55 double std = sqrt( sum / BUCKETS ); 61 mutex( sout ) sout | "trials" | trials| "buckets" | BUCKETS56 mutex( sout ) sout | "trials" | TRIALS | "buckets" | BUCKETS 62 57 | "min" | min | "max" | max 63 58 | "avg" | wd(0,1, avg) | "std" | wd(0,1, std) | "rstd" | wd(0,1, (avg == 0 ? 0.0 : std / avg * 100)) | "%"; … … 69 64 thread T1 {}; 70 65 void main( T1 & ) { 71 size_t * buckets = calloc( BUCKETS );// too big for task stack72 for ( TRIALS / 50 ) {66 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 67 for ( TRIALS / 100 ) { 73 68 buckets[rand() % BUCKETS] += 1; // concurrent 74 69 } // for 75 avgstd( TRIALS / 50,buckets );70 avgstd( buckets ); 76 71 free( buckets ); 77 72 } // main … … 81 76 PRNG prng; 82 77 if ( seed != 0 ) set_seed( prng, seed ); 83 size_t * buckets = calloc( BUCKETS );// too big for task stack78 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 84 79 for ( TRIALS ) { 85 80 buckets[prng( prng ) % BUCKETS] += 1; // concurrent 86 81 } // for 87 avgstd( TRIALS,buckets );82 avgstd( buckets ); 88 83 free( buckets ); 89 84 } // main … … 91 86 thread T3 {}; 92 87 void main( T3 & th ) { 93 size_t * buckets = calloc( BUCKETS );// too big for task stack94 for ( TRIALS / 5) {88 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 89 for ( TRIALS ) { 95 90 buckets[prng() % BUCKETS] += 1; // concurrent 96 91 } // for 97 avgstd( TRIALS / 5,buckets );92 avgstd( buckets ); 98 93 free( buckets ); 99 94 } // main … … 101 96 thread T4 {}; 102 97 void main( T4 & th ) { 103 size_t * buckets = calloc( BUCKETS );// too big for task stack98 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 104 99 for ( TRIALS ) { 105 buckets[prng( th ) % BUCKETS] += 1; // concurrent106 } // for 107 avgstd( TRIALS,buckets );100 buckets[prng( th ) % BUCKETS] += 1; // concurrent 101 } // for 102 avgstd( buckets ); 108 103 free( buckets ); 109 104 } // main … … 113 108 static void dummy( thread$ & th ) __attribute__(( noinline )); 114 109 static void dummy( thread$ & th ) { 115 size_t * buckets = (size_t *)calloc( BUCKETS, sizeof(size_t) ); // too big for task stack116 for ( size_t i = 0; i < TRIALS; i += 1 ) {110 unsigned int * buckets = (unsigned int *)calloc( BUCKETS, sizeof(unsigned int) ); // too big for task stack 111 for ( unsigned int i = 0; i < TRIALS; i += 1 ) { 117 112 buckets[prng( th ) % BUCKETS] += 1; // sequential 118 113 } // for 119 avgstd( TRIALS,buckets );114 avgstd( buckets ); 120 115 free( buckets ); 121 116 } // dummy … … 123 118 124 119 int main() { 125 // setlocale( LC_NUMERIC, getenv( "LANG" ) ); // causes leaked storage message 126 127 // only works on the current pthread thread 120 // causes leaked storage message 121 // setlocale( LC_NUMERIC, getenv( "LANG" ) ); // print digit separator 128 122 // locale_t loc = newlocale( LC_NUMERIC_MASK, getenv( "LANG" ), (locale_t)0p ); 129 123 // if ( loc == (locale_t)0p ) abort( "newlocale" ); … … 132 126 enum { TASKS = 4 }; 133 127 Time start; 134 135 128 #ifdef TIME // too slow for test and generates non-repeatable results 136 129 #if 1 137 sout | "glib rand" | nl | nl; 138 139 size_t rseed; 130 unsigned int rseed; 140 131 if ( seed != 0 ) rseed = seed; 141 132 else rseed = rdtscl(); … … 143 134 144 135 sout | sepDisable; 145 sout | nl |wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" );136 sout | wd(26, "rand()" ) | wd(12, "rand(5)") | wd(12, "rand(0,5)" ); 146 137 for ( 20 ) { 147 138 sout | wd(26, rand()) | nonl; … … 155 146 STARTTIME; 156 147 { 157 size_t * buckets = calloc( BUCKETS );// too big for task stack158 for ( i; TRIALS / 5) {148 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 149 for ( i; TRIALS / 10 ) { 159 150 buckets[rand() % BUCKETS] += 1; // sequential 160 151 } // for 161 avgstd( TRIALS / 5,buckets );152 avgstd( buckets ); 162 153 free( buckets ); 163 154 } 164 ENDTIME( " x 5" );155 ENDTIME( " x 10 " ); 165 156 166 157 sout | nl | "Concurrent"; … … 172 163 } // wait for threads to complete 173 164 } 174 ENDTIME( " x 50 " );165 ENDTIME( " x 100 " ); 175 166 #endif // 0 176 167 #endif // TIME 177 178 sout | nl | "CFA " xstr(PRNG_NAME);179 180 168 #if 1 181 169 PRNG prng; … … 196 184 STARTTIME; 197 185 { 198 size_t * buckets = calloc( BUCKETS );// too big for task stack186 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 199 187 for ( TRIALS ) { 200 188 buckets[prng( prng ) % BUCKETS] += 1; // sequential 201 189 } // for 202 avgstd( TRIALS,buckets );190 avgstd( buckets ); 203 191 free( buckets ); 204 192 } … … 231 219 STARTTIME; 232 220 { 233 size_t * buckets = calloc( BUCKETS );// too big for task stack234 for ( TRIALS / 5) {221 unsigned int * buckets = calloc( BUCKETS ); // too big for task stack 222 for ( TRIALS ) { 235 223 buckets[prng() % BUCKETS] += 1; 236 224 } // for 237 avgstd( TRIALS / 5,buckets );225 avgstd( buckets ); 238 226 free( buckets ); 239 227 } 240 ENDTIME( " x 5 ");228 ENDTIME(); 241 229 242 230 sout | nl | "Concurrent"; … … 248 236 } // wait for threads to complete 249 237 } 250 ENDTIME( " x 5 ");238 ENDTIME(); 251 239 #endif // 0 252 240 #if 1 -
tests/concurrent/waitfor/parse.cfa
r6e1e2d0 ra50fdfb 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2017 University of Waterloo1 //---------------------------------------------------------------------------------------- 2 //---------------------------------------------------------------------------------------- 3 3 // 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 // 4 // DEPRECATED TEST 5 // DIFFERS BETWEEN DEBUG AND RELEASE 6 // 7 //---------------------------------------------------------------------------------------- 8 //---------------------------------------------------------------------------------------- 15 9 16 10 #include <monitor.hfa> … … 18 12 monitor M {}; 19 13 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(); 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 } 50 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 } 72 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 } 28 100 } 29 101 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 ); 98 or else { 99 } 100 101 when( true ) waitfor( notcalled : m, m ); 102 or else { 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: // 102 int main() {} -
tests/pybin/settings.py
r6e1e2d0 ra50fdfb 126 126 global archive 127 127 global install 128 global invariant129 128 130 129 global continue_ … … 141 140 all_install = [Install(o) for o in list(dict.fromkeys(options.install))] 142 141 archive = os.path.abspath(os.path.join(original_path, options.archive_errors)) if options.archive_errors else None 143 invariant = options.invariant144 142 continue_ = options.continue_ 145 143 dry_run = options.dry_run # must be called before tools.config_hash() -
tests/test.py
r6e1e2d0 ra50fdfb 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')117 116 parser.add_argument('--timeout', help='Maximum duration in seconds after a single test is considered to have timed out', type=int, default=180) 118 117 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) … … 173 172 test.prepare() 174 173 175 # extra flags for cfa to pass through make.176 cfa_flags = 'CFAFLAGS=--invariant' if settings.invariant else None177 178 174 # ---------- 179 175 # MAKE … … 181 177 # build, skipping to next test on error 182 178 with Timed() as comp_dur: 183 make_ret, _, _ = make( test.target(), flags=cfa_flags, output_file=subprocess.DEVNULL, error=out_file, error_file=err_file)179 make_ret, _, _ = make( test.target(), output_file=subprocess.DEVNULL, error=out_file, error_file = err_file ) 184 180 185 181 # ----------
Note:
See TracChangeset
for help on using the changeset viewer.