Changeset a505021
- Timestamp:
- Feb 21, 2020, 3:36:36 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- c7a900a
- Parents:
- 8c50aed (diff), c744563a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 30 added
- 3 deleted
- 87 edited
- 17 moved
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
r8c50aed ra505021 215 215 216 216 //Then publish the results 217 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , false, 'Compilation')218 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff' , groupCompile , true , 'Compilation (relative)')219 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch' , groupConcurrency, false, 'Context Switching')220 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff' , groupConcurrency, true , 'Context Switching (relative)')221 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, false, 'Mutual Exclusion')222 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff' , groupConcurrency, true , 'Mutual Exclusion (relative)')223 do_plot(Settings.RunBenchmark && Settings.Publish, 's ignal', groupConcurrency, false, 'Internal and External Scheduling')224 do_plot(Settings.RunBenchmark && Settings.Publish, 's ignal.diff', groupConcurrency, true , 'Internal and External Scheduling (relative)')217 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , false, 'Compilation') 218 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff' , groupCompile , true , 'Compilation (relative)') 219 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch' , groupConcurrency, false, 'Context Switching') 220 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff' , groupConcurrency, true , 'Context Switching (relative)') 221 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, false, 'Mutual Exclusion') 222 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff' , groupConcurrency, true , 'Mutual Exclusion (relative)') 223 do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling' , groupConcurrency, false, 'Internal and External Scheduling') 224 do_plot(Settings.RunBenchmark && Settings.Publish, 'scheduling.diff', groupConcurrency, true , 'Internal and External Scheduling (relative)') 225 225 } 226 226 } -
benchmark/Makefile.am
r8c50aed ra505021 30 30 BENCH_V_UPP = $(__bench_v_UPP_$(__quiet)) 31 31 BENCH_V_GOC = $(__bench_v_GOC_$(__quiet)) 32 BENCH_V_PY = $(__bench_v_PY_$(__quiet)) 32 33 BENCH_V_RUSTC = $(__bench_v_RUSTC_$(__quiet)) 33 34 BENCH_V_NODEJS = $(__bench_v_NODEJS_$(__quiet)) … … 47 48 __bench_v_UPP_verbose = $(AM_V_UPP) 48 49 __bench_v_GOC_verbose = $(AM_V_GOC) 49 __bench_v_RUSTC_verbose = $(AM_V_RUSTC) 50 __bench_v_PY_verbose = $(AM_V_PY) 51 __bench_v_RUSTC_verbose = $(AM_V_RUST) 50 52 __bench_v_NODEJS_verbose = $(AM_V_NODEJS) 51 53 __bench_v_JAVAC_verbose = $(AM_V_JAVAC) … … 72 74 echo "int main() { return 0; }" > ${@} 73 75 74 #.SILENT: # do not print recipe 75 .ONESHELL: # use one shell to execute recipe 76 .SILENT: # do not print recipe 76 77 .NOTPARALLEL: 77 .PHONY: compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv78 .PHONY: jenkins cleancsv 78 79 79 80 ## ========================================================================================================= … … 142 143 FIX_NEW_LINES = cat $@ | tr "\n" "\t" | sed -r 's/\t,/,/' | tr "\t" "\n" > $@ 143 144 144 jenkins$(EXEEXT): 145 cleancsv: 146 rm -f compile.csv basic.csv ctxswitch.csv mutex.csv scheduling.csv 147 148 jenkins$(EXEEXT): cleancsv 145 149 @DOifskipcompile@ 146 150 +make compile.csv 147 151 -+make compile.diff.csv 148 152 @DOendif@ 149 +make basic.csv150 -+make basic.diff.csv151 153 +make ctxswitch.csv 152 154 -+make ctxswitch.diff.csv 153 155 +make mutex.csv 154 156 -+make mutex.diff.csv 155 +make sched int.csv156 -+make sched int.diff.csv157 +make scheduling.csv 158 -+make scheduling.diff.csv 157 159 @DOifskipcompile@ 158 160 cat compile.csv 159 161 -cat compile.diff.csv 160 162 @DOendif@ 161 cat basic.csv162 -cat basic.diff.csv163 163 cat ctxswitch.csv 164 164 -cat ctxswitch.diff.csv 165 165 cat mutex.csv 166 166 -cat mutex.diff.csv 167 cat sched int.csv168 -cat sched int.diff.csv167 cat scheduling.csv 168 -cat scheduling.diff.csv 169 169 170 170 compile.csv: 171 echo "building $@" 171 172 echo "array,attributes,empty,expression,io,monitor,operators,typeof" > $@ 172 173 +make TIME_FORMAT='%e,' PRINT_FORMAT='' compile-array.make >> $@ … … 180 181 $(srcdir)/fixcsv.sh $@ 181 182 182 basic.csv:183 echo "generator,coroutine,thread" > $@184 +make basic-cfa_generator.runquiet >> $@ && echo -n ',' >> $@185 +make basic-cfa_coroutine.runquiet >> $@ && echo -n ',' >> $@186 +make basic-cfa_thread.runquiet >> $@187 $(srcdir)/fixcsv.sh $@188 189 183 ctxswitch.csv: 184 echo "building $@" 190 185 echo "generator,coroutine,thread" > $@ 191 186 +make ctxswitch-cfa_generator.runquiet >> $@ && echo -n ',' >> $@ … … 195 190 196 191 mutex.csv: 192 echo "building $@" 197 193 echo "1-monitor,2-monitor" > $@ 198 194 +make mutex-cfa1.runquiet >> $@ && echo -n ',' >> $@ … … 200 196 $(srcdir)/fixcsv.sh $@ 201 197 202 schedint.csv: 198 scheduling.csv: 199 echo "building $@" 203 200 echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@ 204 201 +make schedint-cfa1.runquiet >> $@ && echo -n ',' >> $@ … … 289 286 290 287 ctxswitch-python_coroutine$(EXEEXT): 291 echo "#!/bin/sh" > a.out288 $(BENCH_V_PY)echo "#!/bin/sh" > a.out 292 289 echo "python3.7 $(srcdir)/ctxswitch/python_cor.py" >> a.out 293 290 chmod a+x a.out 294 291 295 292 ctxswitch-nodejs_coroutine$(EXEEXT): 296 echo "#!/bin/sh" > a.out293 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 297 294 echo "nodejs $(srcdir)/ctxswitch/node_cor.js" >> a.out 298 295 chmod a+x a.out 299 296 300 297 ctxswitch-nodejs_await$(EXEEXT): 301 echo "#!/bin/sh" > a.out298 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 302 299 echo "nodejs $(srcdir)/ctxswitch/node_await.js" >> a.out 303 300 chmod a+x a.out … … 452 449 453 450 creation-python_coroutine$(EXEEXT): 454 echo "#!/bin/sh" > a.out451 $(BENCH_V_PY)echo "#!/bin/sh" > a.out 455 452 echo "python3.7 $(srcdir)/creation/python_cor.py" >> a.out 456 453 chmod a+x a.out 457 454 458 455 creation-nodejs_coroutine$(EXEEXT): 459 echo "#!/bin/sh" > a.out456 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 460 457 echo "nodejs $(srcdir)/creation/node_cor.js" >> a.out 461 458 chmod a+x a.out -
benchmark/Makefile.in
r8c50aed ra505021 368 368 am__v_GOC_0 = @echo " GOC " $@; 369 369 am__v_GOC_1 = 370 AM_V_PY = $(am__v_PY_@AM_V@) 371 am__v_PY_ = $(am__v_PY_@AM_DEFAULT_V@) 372 am__v_PY_0 = @echo " PYTHON " $@; 373 am__v_PY_1 = 370 374 AM_V_RUST = $(am__v_RUST_@AM_V@) 371 375 am__v_RUST_ = $(am__v_RUST_@AM_DEFAULT_V@) 372 am__v_RUST_0 = @echo " RUST 376 am__v_RUST_0 = @echo " RUST " $@; 373 377 am__v_RUST_1 = 374 378 AM_V_NODEJS = $(am__v_NODEJS_@AM_V@) 375 379 am__v_NODEJS_ = $(am__v_NODEJS_@AM_DEFAULT_V@) 376 am__v_NODEJS_0 = @echo " NODEJS 380 am__v_NODEJS_0 = @echo " NODEJS " $@; 377 381 am__v_NODEJS_1 = 378 382 AM_V_JAVAC = $(am__v_JAVAC_@AM_V@) … … 390 394 BENCH_V_UPP = $(__bench_v_UPP_$(__quiet)) 391 395 BENCH_V_GOC = $(__bench_v_GOC_$(__quiet)) 396 BENCH_V_PY = $(__bench_v_PY_$(__quiet)) 392 397 BENCH_V_RUSTC = $(__bench_v_RUSTC_$(__quiet)) 393 398 BENCH_V_NODEJS = $(__bench_v_NODEJS_$(__quiet)) … … 406 411 __bench_v_UPP_verbose = $(AM_V_UPP) 407 412 __bench_v_GOC_verbose = $(AM_V_GOC) 408 __bench_v_RUSTC_verbose = $(AM_V_RUSTC) 413 __bench_v_PY_verbose = $(AM_V_PY) 414 __bench_v_RUSTC_verbose = $(AM_V_RUST) 409 415 __bench_v_NODEJS_verbose = $(AM_V_NODEJS) 410 416 __bench_v_JAVAC_verbose = $(AM_V_JAVAC) … … 784 790 echo "int main() { return 0; }" > ${@} 785 791 786 #.SILENT: # do not print recipe 787 .ONESHELL: # use one shell to execute recipe 792 .SILENT: # do not print recipe 788 793 .NOTPARALLEL: 789 .PHONY: compile.csv basic.csv ctxswitch.csv mutex.csv schedint.csv794 .PHONY: jenkins cleancsv 790 795 791 796 all : basic$(EXEEXT) ctxswitch$(EXEEXT) mutex$(EXEEXT) schedint$(EXEEXT) schedext$(EXEEXT) creation$(EXEEXT) … … 817 822 +make -C ${abs_top_builddir}/tools repeat 818 823 819 jenkins$(EXEEXT): 824 cleancsv: 825 rm -f compile.csv basic.csv ctxswitch.csv mutex.csv scheduling.csv 826 827 jenkins$(EXEEXT): cleancsv 820 828 @DOifskipcompile@ 821 829 +make compile.csv 822 830 -+make compile.diff.csv 823 831 @DOendif@ 824 +make basic.csv825 -+make basic.diff.csv826 832 +make ctxswitch.csv 827 833 -+make ctxswitch.diff.csv 828 834 +make mutex.csv 829 835 -+make mutex.diff.csv 830 +make sched int.csv831 -+make sched int.diff.csv836 +make scheduling.csv 837 -+make scheduling.diff.csv 832 838 @DOifskipcompile@ 833 839 cat compile.csv 834 840 -cat compile.diff.csv 835 841 @DOendif@ 836 cat basic.csv837 -cat basic.diff.csv838 842 cat ctxswitch.csv 839 843 -cat ctxswitch.diff.csv 840 844 cat mutex.csv 841 845 -cat mutex.diff.csv 842 cat sched int.csv843 -cat sched int.diff.csv846 cat scheduling.csv 847 -cat scheduling.diff.csv 844 848 845 849 compile.csv: 850 echo "building $@" 846 851 echo "array,attributes,empty,expression,io,monitor,operators,typeof" > $@ 847 852 +make TIME_FORMAT='%e,' PRINT_FORMAT='' compile-array.make >> $@ … … 855 860 $(srcdir)/fixcsv.sh $@ 856 861 857 basic.csv:858 echo "generator,coroutine,thread" > $@859 +make basic-cfa_generator.runquiet >> $@ && echo -n ',' >> $@860 +make basic-cfa_coroutine.runquiet >> $@ && echo -n ',' >> $@861 +make basic-cfa_thread.runquiet >> $@862 $(srcdir)/fixcsv.sh $@863 864 862 ctxswitch.csv: 863 echo "building $@" 865 864 echo "generator,coroutine,thread" > $@ 866 865 +make ctxswitch-cfa_generator.runquiet >> $@ && echo -n ',' >> $@ … … 870 869 871 870 mutex.csv: 871 echo "building $@" 872 872 echo "1-monitor,2-monitor" > $@ 873 873 +make mutex-cfa1.runquiet >> $@ && echo -n ',' >> $@ … … 875 875 $(srcdir)/fixcsv.sh $@ 876 876 877 schedint.csv: 877 scheduling.csv: 878 echo "building $@" 878 879 echo "schedint-1,schedint-2,schedext-1,schedext-2" > $@ 879 880 +make schedint-cfa1.runquiet >> $@ && echo -n ',' >> $@ … … 931 932 932 933 ctxswitch-python_coroutine$(EXEEXT): 933 echo "#!/bin/sh" > a.out934 $(BENCH_V_PY)echo "#!/bin/sh" > a.out 934 935 echo "python3.7 $(srcdir)/ctxswitch/python_cor.py" >> a.out 935 936 chmod a+x a.out 936 937 937 938 ctxswitch-nodejs_coroutine$(EXEEXT): 938 echo "#!/bin/sh" > a.out939 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 939 940 echo "nodejs $(srcdir)/ctxswitch/node_cor.js" >> a.out 940 941 chmod a+x a.out 941 942 942 943 ctxswitch-nodejs_await$(EXEEXT): 943 echo "#!/bin/sh" > a.out944 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 944 945 echo "nodejs $(srcdir)/ctxswitch/node_await.js" >> a.out 945 946 chmod a+x a.out … … 1085 1086 1086 1087 creation-python_coroutine$(EXEEXT): 1087 echo "#!/bin/sh" > a.out1088 $(BENCH_V_PY)echo "#!/bin/sh" > a.out 1088 1089 echo "python3.7 $(srcdir)/creation/python_cor.py" >> a.out 1089 1090 chmod a+x a.out 1090 1091 1091 1092 creation-nodejs_coroutine$(EXEEXT): 1092 echo "#!/bin/sh" > a.out1093 $(BENCH_V_NODEJS)echo "#!/bin/sh" > a.out 1093 1094 echo "nodejs $(srcdir)/creation/node_cor.js" >> a.out 1094 1095 chmod a+x a.out -
benchmark/baselines/x64/schedint.csv
r8c50aed ra505021 1 waitfor-2,signal-1,signal-2,waitfor-11 schedext-2,schedint-1,schedint-2,schedext-1 2 2 393.69606249999987,325.99158333333327,409.01025000000004,319.90975000000003 -
benchmark/baselines/x86/schedint.csv
r8c50aed ra505021 1 s ignal-2,waitfor-1,waitfor-2,signal-11 schedint-2,schedext-1,schedext-2,schedint-1 2 2 532.5297959183672,413.3084897959184,506.7579591836735,423.78826530612247 -
doc/theses/thierry_delisle_PhD/code/relaxed_list.cpp
r8c50aed ra505021 9 9 #include <vector> 10 10 11 #include <getopt.h> 11 12 #include <unistd.h> 12 13 #include <sys/sysinfo.h> … … 21 22 22 23 int value; 23 Node(int value): value(value) { 24 creates++; 25 } 26 27 ~Node() { 28 destroys++; 29 } 24 int id; 25 26 Node() { creates++; } 27 Node(int value): value(value) { creates++; } 28 ~Node() { destroys++; } 30 29 }; 31 30 … … 33 32 std::atomic_size_t Node::destroys = { 0 }; 34 33 35 static const constexpr int nodes_per_threads = 128;36 struct NodeArray {37 __attribute__((aligned(64))) Node * array[nodes_per_threads];38 __attribute__((aligned(64))) char pad;39 };40 41 34 bool enable_stats = false; 35 36 template<> 37 thread_local relaxed_list<Node>::TLS relaxed_list<Node>::tls = {}; 38 39 template<> 40 relaxed_list<Node> * relaxed_list<Node>::head = nullptr; 41 42 #ifndef NO_STATS 43 template<> 44 relaxed_list<Node>::GlobalStats relaxed_list<Node>::global_stats = {}; 45 #endif 46 47 // ================================================================================================ 48 // UTILS 49 // ================================================================================================ 42 50 43 51 struct local_stat_t { … … 47 55 size_t crc_in = 0; 48 56 size_t crc_out = 0; 57 size_t valmax = 0; 58 size_t valmin = 100000000ul; 49 59 }; 50 60 51 __attribute__((noinline)) void run_body( 52 std::atomic<bool>& done, 53 Random & rand, 54 Node * (&my_nodes)[128], 55 local_stat_t & local, 56 relaxed_list<Node> & list 57 ) { 58 while(__builtin_expect(!done.load(std::memory_order_relaxed), true)) { 59 int idx = rand.next() % nodes_per_threads; 60 if (auto node = my_nodes[idx]) { 61 local.crc_in += node->value; 62 list.push(node); 63 my_nodes[idx] = nullptr; 64 local.in++; 65 } 66 else if(auto node = list.pop()) { 67 local.crc_out += node->value; 68 my_nodes[idx] = node; 69 local.out++; 70 } 71 else { 72 local.empty++; 73 } 74 } 75 } 76 77 void run(unsigned nthread, unsigned nqueues, unsigned fill, double duration) { 78 // List being tested 79 relaxed_list<Node> list = { nthread * nqueues }; 80 81 // Barrier for synchronization 82 barrier_t barrier(nthread + 1); 83 84 // Data to check everything is OK 85 struct { 86 std::atomic_size_t in = { 0 }; 87 std::atomic_size_t out = { 0 }; 88 std::atomic_size_t empty = { 0 }; 89 std::atomic_size_t crc_in = { 0 }; 90 std::atomic_size_t crc_out = { 0 }; 91 struct { 92 struct { 93 std::atomic_size_t attempt = { 0 }; 94 std::atomic_size_t success = { 0 }; 95 } push; 96 struct { 97 std::atomic_size_t attempt = { 0 }; 98 std::atomic_size_t success = { 0 }; 99 } pop; 100 } pick; 101 } global; 102 103 // Flag to signal termination 104 std::atomic_bool done = { false }; 105 106 // Prep nodes 107 std::cout << "Initializing "; 108 size_t nnodes = 0; 109 size_t npushed = 0; 110 NodeArray all_nodes[nthread]; 111 for(auto & nodes : all_nodes) { 112 Random rand(rdtscl()); 113 for(auto & node : nodes.array) { 114 auto r = rand.next() % 100; 115 if(r < fill) { 116 node = new Node(rand.next() % 100); 117 nnodes++; 118 } else { 119 node = nullptr; 120 } 121 } 122 123 for(int i = 0; i < 10; i++) { 124 int idx = rand.next() % nodes_per_threads; 125 if (auto node = nodes.array[idx]) { 126 global.crc_in += node->value; 127 list.push(node); 128 npushed++; 129 nodes.array[idx] = nullptr; 130 } 131 } 132 } 133 134 std::cout << nnodes << " nodes " << fill << "% (" << npushed << " pushed)" << std::endl; 135 136 enable_stats = true; 137 138 std::thread * threads[nthread]; 139 unsigned i = 1; 140 for(auto & t : threads) { 141 auto & my_nodes = all_nodes[i - 1].array; 142 t = new std::thread([&done, &list, &barrier, &global, &my_nodes](unsigned tid) { 143 Random rand(tid + rdtscl()); 144 145 local_stat_t local; 146 147 // affinity(tid); 148 149 barrier.wait(tid); 150 151 // EXPERIMENT START 152 153 run_body(done, rand, my_nodes, local, list); 154 155 // EXPERIMENT END 156 157 barrier.wait(tid); 158 159 global.in += local.in; 160 global.out += local.out; 161 global.empty += local.empty; 162 163 for(auto node : my_nodes) { 164 delete node; 165 } 166 167 global.crc_in += local.crc_in; 168 global.crc_out += local.crc_out; 169 170 global.pick.push.attempt += relaxed_list<Node>::tls.pick.push.attempt; 171 global.pick.push.success += relaxed_list<Node>::tls.pick.push.success; 172 global.pick.pop .attempt += relaxed_list<Node>::tls.pick.pop.attempt; 173 global.pick.pop .success += relaxed_list<Node>::tls.pick.pop.success; 174 }, i++); 175 } 176 61 struct global_stat_t { 62 std::atomic_size_t in = { 0 }; 63 std::atomic_size_t out = { 0 }; 64 std::atomic_size_t empty = { 0 }; 65 std::atomic_size_t crc_in = { 0 }; 66 std::atomic_size_t crc_out = { 0 }; 67 std::atomic_size_t valmax = { 0 }; 68 std::atomic_size_t valmin = { 100000000ul }; 69 }; 70 71 void atomic_max(std::atomic_size_t & target, size_t value) { 72 for(;;) { 73 size_t expect = target.load(std::memory_order_relaxed); 74 if(value <= expect) return; 75 bool success = target.compare_exchange_strong(expect, value); 76 if(success) return; 77 } 78 } 79 80 void atomic_min(std::atomic_size_t & target, size_t value) { 81 for(;;) { 82 size_t expect = target.load(std::memory_order_relaxed); 83 if(value >= expect) return; 84 bool success = target.compare_exchange_strong(expect, value); 85 if(success) return; 86 } 87 } 88 89 void tally_stats(global_stat_t & global, local_stat_t & local) { 90 91 global.in += local.in; 92 global.out += local.out; 93 global.empty += local.empty; 94 95 global.crc_in += local.crc_in; 96 global.crc_out += local.crc_out; 97 98 atomic_max(global.valmax, local.valmax); 99 atomic_min(global.valmin, local.valmin); 100 101 relaxed_list<Node>::stats_tls_tally(); 102 } 103 104 void waitfor(double & duration, barrier_t & barrier, std::atomic_bool & done) { 177 105 std::cout << "Starting" << std::endl; 178 106 auto before = Clock::now(); … … 196 124 duration = durr.count(); 197 125 std::cout << "\rClosing down" << std::endl; 198 199 for(auto t : threads) { 200 t->join(); 201 delete t; 202 } 203 204 enable_stats = false; 205 206 while(auto node = list.pop()) { 207 global.crc_out += node->value; 208 delete node; 209 } 210 126 } 127 128 void waitfor(double & duration, barrier_t & barrier, const std::atomic_size_t & count) { 129 std::cout << "Starting" << std::endl; 130 auto before = Clock::now(); 131 barrier.wait(0); 132 133 while(true) { 134 usleep(100000); 135 size_t c = count.load(); 136 if( c == 0 ) { 137 break; 138 } 139 std::cout << "\r" << c; 140 std::cout.flush(); 141 } 142 143 barrier.wait(0); 144 auto after = Clock::now(); 145 duration_t durr = after - before; 146 duration = durr.count(); 147 std::cout << "\rClosing down" << std::endl; 148 } 149 150 void print_stats(double duration, unsigned nthread, global_stat_t & global) { 211 151 assert(Node::creates == Node::destroys); 212 152 assert(global.crc_in == global.crc_out); … … 224 164 std::cout << "Ops/sec : " << ops_sec << "\n"; 225 165 std::cout << "Total ops : " << ops << "(" << global.in << "i, " << global.out << "o, " << global.empty << "e)\n"; 166 if(global.valmax != 0) { 167 std::cout << "Max runs : " << global.valmax << "\n"; 168 std::cout << "Min runs : " << global.valmin << "\n"; 169 } 226 170 #ifndef NO_STATS 227 double push_sur = (100.0 * double(global.pick.push.success) / global.pick.push.attempt); 228 double pop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .attempt); 229 std::cout << "Push Pick % : " << push_sur << "(" << global.pick.push.success << " / " << global.pick.push.attempt << ")\n"; 230 std::cout << "Pop Pick % : " << pop_sur << "(" << global.pick.pop .success << " / " << global.pick.pop .attempt << ")\n"; 171 relaxed_list<Node>::stats_print(std::cout); 231 172 #endif 232 173 } 233 174 234 void usage(char * argv[]) { 235 std::cerr << argv[0] << ": [DURATION (FLOAT:SEC)] [NTHREADS] [NQUEUES] [FILL]" << std::endl;; 236 std::exit(1); 175 void save_fairness(const int data[], int factor, unsigned nthreads, size_t columns, size_t rows, const std::string & output); 176 177 // ================================================================================================ 178 // EXPERIMENTS 179 // ================================================================================================ 180 181 // ================================================================================================ 182 __attribute__((noinline)) void runChurn_body( 183 std::atomic<bool>& done, 184 Random & rand, 185 Node * my_nodes[], 186 unsigned nslots, 187 local_stat_t & local, 188 relaxed_list<Node> & list 189 ) { 190 while(__builtin_expect(!done.load(std::memory_order_relaxed), true)) { 191 int idx = rand.next() % nslots; 192 if (auto node = my_nodes[idx]) { 193 local.crc_in += node->value; 194 list.push(node); 195 my_nodes[idx] = nullptr; 196 local.in++; 197 } 198 else if(auto node = list.pop()) { 199 local.crc_out += node->value; 200 my_nodes[idx] = node; 201 local.out++; 202 } 203 else { 204 local.empty++; 205 } 206 } 207 } 208 209 void runChurn(unsigned nthread, unsigned nqueues, double duration, unsigned nnodes, const unsigned nslots) { 210 std::cout << "Churn Benchmark" << std::endl; 211 assert(nnodes <= nslots); 212 // List being tested 213 214 // Barrier for synchronization 215 barrier_t barrier(nthread + 1); 216 217 // Data to check everything is OK 218 global_stat_t global; 219 220 // Flag to signal termination 221 std::atomic_bool done = { false }; 222 223 // Prep nodes 224 std::cout << "Initializing "; 225 size_t npushed = 0; 226 relaxed_list<Node> list = { nthread * nqueues }; 227 { 228 Node** all_nodes[nthread]; 229 for(auto & nodes : all_nodes) { 230 nodes = new __attribute__((aligned(64))) Node*[nslots + 8]; 231 Random rand(rdtscl()); 232 for(unsigned i = 0; i < nnodes; i++) { 233 nodes[i] = new Node(rand.next() % 100); 234 } 235 236 for(unsigned i = nnodes; i < nslots; i++) { 237 nodes[i] = nullptr; 238 } 239 240 for(int i = 0; i < 10 && i < (int)nslots; i++) { 241 int idx = rand.next() % nslots; 242 if (auto node = nodes[idx]) { 243 global.crc_in += node->value; 244 list.push(node); 245 npushed++; 246 nodes[idx] = nullptr; 247 } 248 } 249 } 250 251 std::cout << nnodes << " nodes (" << nslots << " slots)" << std::endl; 252 253 enable_stats = true; 254 255 std::thread * threads[nthread]; 256 unsigned i = 1; 257 for(auto & t : threads) { 258 auto & my_nodes = all_nodes[i - 1]; 259 t = new std::thread([&done, &list, &barrier, &global, &my_nodes, nslots](unsigned tid) { 260 Random rand(tid + rdtscl()); 261 262 local_stat_t local; 263 264 // affinity(tid); 265 266 barrier.wait(tid); 267 268 // EXPERIMENT START 269 270 runChurn_body(done, rand, my_nodes, nslots, local, list); 271 272 // EXPERIMENT END 273 274 barrier.wait(tid); 275 276 tally_stats(global, local); 277 278 for(unsigned i = 0; i < nslots; i++) { 279 delete my_nodes[i]; 280 } 281 }, i++); 282 } 283 284 waitfor(duration, barrier, done); 285 286 for(auto t : threads) { 287 t->join(); 288 delete t; 289 } 290 291 enable_stats = false; 292 293 while(auto node = list.pop()) { 294 global.crc_out += node->value; 295 delete node; 296 } 297 298 for(auto nodes : all_nodes) { 299 delete[] nodes; 300 } 301 } 302 303 print_stats(duration, nthread, global); 304 } 305 306 // ================================================================================================ 307 __attribute__((noinline)) void runPingPong_body( 308 std::atomic<bool>& done, 309 Node initial_nodes[], 310 unsigned nnodes, 311 local_stat_t & local, 312 relaxed_list<Node> & list 313 ) { 314 Node * nodes[nnodes]; 315 { 316 unsigned i = 0; 317 for(auto & n : nodes) { 318 n = &initial_nodes[i++]; 319 } 320 } 321 322 while(__builtin_expect(!done.load(std::memory_order_relaxed), true)) { 323 324 for(Node * & node : nodes) { 325 local.crc_in += node->value; 326 list.push(node); 327 local.in++; 328 } 329 330 // ----- 331 332 for(Node * & node : nodes) { 333 node = list.pop(); 334 assert(node); 335 local.crc_out += node->value; 336 local.out++; 337 } 338 } 339 } 340 341 void runPingPong(unsigned nthread, unsigned nqueues, double duration, unsigned nnodes) { 342 std::cout << "PingPong Benchmark" << std::endl; 343 344 345 // Barrier for synchronization 346 barrier_t barrier(nthread + 1); 347 348 // Data to check everything is OK 349 global_stat_t global; 350 351 // Flag to signal termination 352 std::atomic_bool done = { false }; 353 354 std::cout << "Initializing "; 355 // List being tested 356 relaxed_list<Node> list = { nthread * nqueues }; 357 { 358 enable_stats = true; 359 360 std::thread * threads[nthread]; 361 unsigned i = 1; 362 for(auto & t : threads) { 363 t = new std::thread([&done, &list, &barrier, &global, nnodes](unsigned tid) { 364 Random rand(tid + rdtscl()); 365 366 Node nodes[nnodes]; 367 for(auto & n : nodes) { 368 n.value = (int)rand.next() % 100; 369 } 370 371 local_stat_t local; 372 373 // affinity(tid); 374 375 barrier.wait(tid); 376 377 // EXPERIMENT START 378 379 runPingPong_body(done, nodes, nnodes, local, list); 380 381 // EXPERIMENT END 382 383 barrier.wait(tid); 384 385 tally_stats(global, local); 386 }, i++); 387 } 388 389 waitfor(duration, barrier, done); 390 391 for(auto t : threads) { 392 t->join(); 393 delete t; 394 } 395 396 enable_stats = false; 397 } 398 399 print_stats(duration, nthread, global); 400 } 401 402 // ================================================================================================ 403 __attribute__((noinline)) void runFairness_body( 404 unsigned tid, 405 size_t width, 406 size_t length, 407 int output[], 408 std::atomic_size_t & count, 409 Node initial_nodes[], 410 unsigned nnodes, 411 local_stat_t & local, 412 relaxed_list<Node> & list 413 ) { 414 Node * nodes[nnodes]; 415 { 416 unsigned i = 0; 417 for(auto & n : nodes) { 418 n = &initial_nodes[i++]; 419 } 420 } 421 422 while(__builtin_expect(0 != count.load(std::memory_order_relaxed), true)) { 423 424 for(Node * & node : nodes) { 425 local.crc_in += node->id; 426 list.push(node); 427 local.in++; 428 } 429 430 // ----- 431 432 for(Node * & node : nodes) { 433 node = list.pop(); 434 assert(node); 435 436 if (unsigned(node->value) < length) { 437 size_t idx = (node->value * width) + node->id; 438 assert(idx < (width * length)); 439 output[idx] = tid; 440 } 441 442 node->value++; 443 if(unsigned(node->value) == length) count--; 444 445 local.crc_out += node->id; 446 local.out++; 447 } 448 } 449 } 450 451 void runFairness(unsigned nthread, unsigned nqueues, double duration, unsigned nnodes, const std::string & output) { 452 std::cout << "Fairness Benchmark, outputing to : " << output << std::endl; 453 454 // Barrier for synchronization 455 barrier_t barrier(nthread + 1); 456 457 // Data to check everything is OK 458 global_stat_t global; 459 460 std::cout << "Initializing "; 461 462 // Check fairness by creating a png of where the threads ran 463 size_t width = nthread * nnodes; 464 size_t length = 100000; 465 466 std::unique_ptr<int[]> data_out { new int[width * length] }; 467 468 // Flag to signal termination 469 std::atomic_size_t count = width; 470 471 // List being tested 472 relaxed_list<Node> list = { nthread * nqueues }; 473 { 474 enable_stats = true; 475 476 std::thread * threads[nthread]; 477 unsigned i = 1; 478 for(auto & t : threads) { 479 t = new std::thread([&count, &list, &barrier, &global, nnodes, width, length, data_out = data_out.get()](unsigned tid) { 480 unsigned int start = (tid - 1) * nnodes; 481 Node nodes[nnodes]; 482 for(auto & n : nodes) { 483 n.id = start; 484 n.value = 0; 485 start++; 486 } 487 488 local_stat_t local; 489 490 // affinity(tid); 491 492 barrier.wait(tid); 493 494 // EXPERIMENT START 495 496 runFairness_body(tid, width, length, data_out, count, nodes, nnodes, local, list); 497 498 // EXPERIMENT END 499 500 barrier.wait(tid); 501 502 for(const auto & n : nodes) { 503 local.valmax = max(local.valmax, size_t(n.value)); 504 local.valmin = min(local.valmin, size_t(n.value)); 505 } 506 507 tally_stats(global, local); 508 }, i++); 509 } 510 511 waitfor(duration, barrier, count); 512 513 for(auto t : threads) { 514 t->join(); 515 delete t; 516 } 517 518 enable_stats = false; 519 } 520 521 print_stats(duration, nthread, global); 522 523 save_fairness(data_out.get(), 100, nthread, width, length, output); 524 } 525 526 // ================================================================================================ 527 528 bool iequals(const std::string& a, const std::string& b) 529 { 530 return std::equal(a.begin(), a.end(), 531 b.begin(), b.end(), 532 [](char a, char b) { 533 return std::tolower(a) == std::tolower(b); 534 }); 237 535 } 238 536 … … 241 539 double duration = 5.0; 242 540 unsigned nthreads = 2; 243 unsigned nqueues = 2; 244 unsigned fill = 100; 541 unsigned nqueues = 4; 542 unsigned nnodes = 100; 543 unsigned nslots = 100; 544 std::string out = "fairness.png"; 545 546 enum { 547 Churn, 548 PingPong, 549 Fairness, 550 NONE 551 } benchmark = NONE; 245 552 246 553 std::cout.imbue(std::locale("")); 247 554 248 switch (argc) 249 { 555 for(;;) { 556 static struct option options[] = { 557 {"duration", required_argument, 0, 'd'}, 558 {"nthreads", required_argument, 0, 't'}, 559 {"nqueues", required_argument, 0, 'q'}, 560 {"benchmark", required_argument, 0, 'b'}, 561 {0, 0, 0, 0} 562 }; 563 564 int idx = 0; 565 int opt = getopt_long(argc, argv, "d:t:q:b:", options, &idx); 566 567 std::string arg = optarg ? optarg : ""; 568 size_t len = 0; 569 switch(opt) { 570 // Exit Case 571 case -1: 572 /* paranoid */ assert(optind <= argc); 573 switch(benchmark) { 574 case NONE: 575 std::cerr << "Must specify a benchmark" << std::endl; 576 goto usage; 577 case PingPong: 578 nnodes = 1; 579 nslots = 1; 580 switch(argc - optind) { 581 case 0: break; 582 case 1: 583 try { 584 arg = optarg = argv[optind]; 585 nnodes = stoul(optarg, &len); 586 if(len != arg.size()) { throw std::invalid_argument(""); } 587 } catch(std::invalid_argument &) { 588 std::cerr << "Number of nodes must be a positive integer, was " << arg << std::endl; 589 goto usage; 590 } 591 break; 592 default: 593 std::cerr << "'PingPong' benchmark doesn't accept more than 2 extra arguments" << std::endl; 594 goto usage; 595 } 596 break; 597 case Churn: 598 nnodes = 100; 599 nslots = 100; 600 switch(argc - optind) { 601 case 0: break; 602 case 1: 603 try { 604 arg = optarg = argv[optind]; 605 nnodes = stoul(optarg, &len); 606 if(len != arg.size()) { throw std::invalid_argument(""); } 607 nslots = nnodes; 608 } catch(std::invalid_argument &) { 609 std::cerr << "Number of nodes must be a positive integer, was " << arg << std::endl; 610 goto usage; 611 } 612 break; 613 case 2: 614 try { 615 arg = optarg = argv[optind]; 616 nnodes = stoul(optarg, &len); 617 if(len != arg.size()) { throw std::invalid_argument(""); } 618 } catch(std::invalid_argument &) { 619 std::cerr << "Number of nodes must be a positive integer, was " << arg << std::endl; 620 goto usage; 621 } 622 try { 623 arg = optarg = argv[optind + 1]; 624 nslots = stoul(optarg, &len); 625 if(len != arg.size()) { throw std::invalid_argument(""); } 626 } catch(std::invalid_argument &) { 627 std::cerr << "Number of slots must be a positive integer, was " << arg << std::endl; 628 goto usage; 629 } 630 break; 631 default: 632 std::cerr << "'Churn' benchmark doesn't accept more than 2 extra arguments" << std::endl; 633 goto usage; 634 } 635 break; 636 case Fairness: 637 nnodes = 1; 638 switch(argc - optind) { 639 case 0: break; 640 case 1: 641 arg = optarg = argv[optind]; 642 out = arg; 643 break; 644 default: 645 std::cerr << "'Churn' benchmark doesn't accept more than 2 extra arguments" << std::endl; 646 goto usage; 647 } 648 } 649 goto run; 650 // Benchmarks 651 case 'b': 652 if(benchmark != NONE) { 653 std::cerr << "Only when benchmark can be run" << std::endl; 654 goto usage; 655 } 656 if(iequals(arg, "churn")) { 657 benchmark = Churn; 658 break; 659 } 660 if(iequals(arg, "pingpong")) { 661 benchmark = PingPong; 662 break; 663 } 664 if(iequals(arg, "fairness")) { 665 benchmark = Fairness; 666 break; 667 } 668 std::cerr << "Unkown benchmark " << arg << std::endl; 669 goto usage; 670 // Numeric Arguments 671 case 'd': 672 try { 673 duration = stod(optarg, &len); 674 if(len != arg.size()) { throw std::invalid_argument(""); } 675 } catch(std::invalid_argument &) { 676 std::cerr << "Duration must be a valid double, was " << arg << std::endl; 677 goto usage; 678 } 679 break; 680 case 't': 681 try { 682 nthreads = stoul(optarg, &len); 683 if(len != arg.size()) { throw std::invalid_argument(""); } 684 } catch(std::invalid_argument &) { 685 std::cerr << "Number of threads must be a positive integer, was " << arg << std::endl; 686 goto usage; 687 } 688 break; 689 case 'q': 690 try { 691 nqueues = stoul(optarg, &len); 692 if(len != arg.size()) { throw std::invalid_argument(""); } 693 } catch(std::invalid_argument &) { 694 std::cerr << "Number of queues must be a positive integer, was " << arg << std::endl; 695 goto usage; 696 } 697 break; 698 // Other cases 699 default: /* ? */ 700 std::cerr << opt << std::endl; 701 usage: 702 std::cerr << "Usage: " << argv[0] << ": [options] -b churn [NNODES] [NSLOTS = NNODES]" << std::endl; 703 std::cerr << " or: " << argv[0] << ": [options] -b pingpong [NNODES]" << std::endl; 704 std::cerr << std::endl; 705 std::cerr << " -d, --duration=DURATION Duration of the experiment, in seconds" << std::endl; 706 std::cerr << " -t, --nthreads=NTHREADS Number of kernel threads" << std::endl; 707 std::cerr << " -q, --nqueues=NQUEUES Number of queues per threads" << std::endl; 708 std::exit(1); 709 } 710 } 711 run: 712 713 check_cache_line_size(); 714 715 std::cout << "Running " << nthreads << " threads (" << (nthreads * nqueues) << " queues) for " << duration << " seconds" << std::endl; 716 switch(benchmark) { 717 case Churn: 718 runChurn(nthreads, nqueues, duration, nnodes, nslots); 719 break; 720 case PingPong: 721 runPingPong(nthreads, nqueues, duration, nnodes); 722 break; 723 case Fairness: 724 runFairness(nthreads, nqueues, duration, nnodes, out); 725 break; 726 default: 727 abort(); 728 } 729 return 0; 730 } 731 732 const char * __my_progname = "Relaxed List"; 733 734 struct rgb_t { 735 double r; // a fraction between 0 and 1 736 double g; // a fraction between 0 and 1 737 double b; // a fraction between 0 and 1 738 }; 739 740 struct hsv_t { 741 double h; // angle in degrees 742 double s; // a fraction between 0 and 1 743 double v; // a fraction between 0 and 1 744 }; 745 746 rgb_t hsv2rgb(hsv_t in) { 747 double hh, p, q, t, ff; 748 long i; 749 rgb_t out; 750 751 if(in.s <= 0.0) { // < is bogus, just shuts up warnings 752 out.r = in.v; 753 out.g = in.v; 754 out.b = in.v; 755 return out; 756 } 757 hh = in.h; 758 if(hh >= 360.0) hh = 0.0; 759 hh /= 60.0; 760 i = (long)hh; 761 ff = hh - i; 762 p = in.v * (1.0 - in.s); 763 q = in.v * (1.0 - (in.s * ff)); 764 t = in.v * (1.0 - (in.s * (1.0 - ff))); 765 766 switch(i) { 767 case 0: 768 out.r = in.v; 769 out.g = t; 770 out.b = p; 771 break; 772 case 1: 773 out.r = q; 774 out.g = in.v; 775 out.b = p; 776 break; 777 case 2: 778 out.r = p; 779 out.g = in.v; 780 out.b = t; 781 break; 782 783 case 3: 784 out.r = p; 785 out.g = q; 786 out.b = in.v; 787 break; 788 case 4: 789 out.r = t; 790 out.g = p; 791 out.b = in.v; 792 break; 250 793 case 5: 251 fill = std::stoul(argv[4]); 252 [[fallthrough]]; 253 case 4: 254 nqueues = std::stoul(argv[3]); 255 [[fallthrough]]; 256 case 3: 257 nthreads = std::stoul(argv[2]); 258 [[fallthrough]]; 259 case 2: 260 duration = std::stod(argv[1]); 261 if( duration <= 0.0 ) { 262 std::cerr << "Duration must be positive, was " << argv[1] << "(" << duration << ")" << std::endl; 263 usage(argv); 264 } 265 [[fallthrough]]; 266 case 1: 794 default: 795 out.r = in.v; 796 out.g = p; 797 out.b = q; 267 798 break; 268 default: 269 usage(argv); 270 break; 271 } 272 273 check_cache_line_size(); 274 275 std::cout << "Running " << nthreads << " threads (" << (nthreads * nqueues) << " queues) for " << duration << " seconds" << std::endl; 276 run(nthreads, nqueues, fill, duration); 277 278 return 0; 279 } 280 281 template<> 282 thread_local relaxed_list<Node>::TLS relaxed_list<Node>::tls = {}; 283 284 template<> 285 relaxed_list<Node>::intrusive_queue_t::stat::Dif relaxed_list<Node>::intrusive_queue_t::stat::dif = {}; 286 287 const char * __my_progname = "Relaxed List"; 799 } 800 return out; 801 } 802 803 void save_fairness(const int data[], int factor, unsigned nthreads, size_t columns, size_t rows, const std::string & output) { 804 std::ofstream os(output); 805 os << "<html>\n"; 806 os << "<head>\n"; 807 os << "<style>\n"; 808 os << "</style>\n"; 809 os << "</head>\n"; 810 os << "<body>\n"; 811 os << "<table style=\"width=100%\">\n"; 812 813 size_t idx = 0; 814 for(size_t r = 0ul; r < rows; r++) { 815 os << "<tr>\n"; 816 for(size_t c = 0ul; c < columns; c++) { 817 os << "<td class=\"custom custom" << data[idx] << "\"></td>\n"; 818 idx++; 819 } 820 os << "</tr>\n"; 821 } 822 823 os << "</table>\n"; 824 os << "</body>\n"; 825 os << "</html>\n"; 826 os << std::endl; 827 } 828 829 #include <png.h> 830 #include <setjmp.h> 831 832 /* 833 void save_fairness(const int data[], int factor, unsigned nthreads, size_t columns, size_t rows, const std::string & output) { 834 int width = columns * factor; 835 int height = rows / factor; 836 837 int code = 0; 838 int idx = 0; 839 FILE *fp = NULL; 840 png_structp png_ptr = NULL; 841 png_infop info_ptr = NULL; 842 png_bytep row = NULL; 843 844 // Open file for writing (binary mode) 845 fp = fopen(output.c_str(), "wb"); 846 if (fp == NULL) { 847 fprintf(stderr, "Could not open file %s for writing\n", output.c_str()); 848 code = 1; 849 goto finalise; 850 } 851 852 // Initialize write structure 853 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 854 if (png_ptr == NULL) { 855 fprintf(stderr, "Could not allocate write struct\n"); 856 code = 1; 857 goto finalise; 858 } 859 860 // Initialize info structure 861 info_ptr = png_create_info_struct(png_ptr); 862 if (info_ptr == NULL) { 863 fprintf(stderr, "Could not allocate info struct\n"); 864 code = 1; 865 goto finalise; 866 } 867 868 // Setup Exception handling 869 if (setjmp(png_jmpbuf(png_ptr))) { 870 fprintf(stderr, "Error during png creation\n"); 871 code = 1; 872 goto finalise; 873 } 874 875 png_init_io(png_ptr, fp); 876 877 // Write header (8 bit colour depth) 878 png_set_IHDR(png_ptr, info_ptr, width, height, 879 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, 880 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 881 882 png_write_info(png_ptr, info_ptr); 883 884 // Allocate memory for one row (3 bytes per pixel - RGB) 885 row = (png_bytep) malloc(3 * width * sizeof(png_byte)); 886 887 // Write image data 888 int x, y; 889 for (y=0 ; y<height ; y++) { 890 for (x=0 ; x<width ; x++) { 891 auto & r = row[(x * 3) + 0]; 892 auto & g = row[(x * 3) + 1]; 893 auto & b = row[(x * 3) + 2]; 894 assert(idx < (rows * columns)); 895 int color = data[idx] - 1; 896 assert(color < nthreads); 897 assert(color >= 0); 898 idx++; 899 900 double angle = double(color) / double(nthreads); 901 902 auto c = hsv2rgb({ 360.0 * angle, 0.8, 0.8 }); 903 904 r = char(c.r * 255.0); 905 g = char(c.g * 255.0); 906 b = char(c.b * 255.0); 907 908 } 909 png_write_row(png_ptr, row); 910 } 911 912 assert(idx == (rows * columns)); 913 914 // End write 915 png_write_end(png_ptr, NULL); 916 917 finalise: 918 if (fp != NULL) fclose(fp); 919 if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); 920 if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 921 if (row != NULL) free(row); 922 } 923 */ -
doc/theses/thierry_delisle_PhD/code/relaxed_list.hpp
r8c50aed ra505021 37 37 }; 38 38 39 static inline bool bts(std::atomic_size_t & target, size_t bit ) { 40 //* 41 int result = 0; 42 asm volatile( 43 "LOCK btsq %[bit], %[target]\n\t" 44 :"=@ccc" (result) 45 : [target] "m" (target), [bit] "r" (bit) 46 ); 47 return result != 0; 48 /*/ 49 size_t mask = 1ul << bit; 50 size_t ret = target.fetch_or(mask, std::memory_order_relaxed); 51 return (ret & mask) != 0; 52 //*/ 53 } 54 55 static inline bool btr(std::atomic_size_t & target, size_t bit ) { 56 //* 57 int result = 0; 58 asm volatile( 59 "LOCK btrq %[bit], %[target]\n\t" 60 :"=@ccc" (result) 61 : [target] "m" (target), [bit] "r" (bit) 62 ); 63 return result != 0; 64 /*/ 65 size_t mask = 1ul << bit; 66 size_t ret = target.fetch_and(~mask, std::memory_order_relaxed); 67 return (ret & mask) != 0; 68 //*/ 69 } 39 70 40 71 extern bool enable_stats; … … 48 79 size_t attempt = 0; 49 80 size_t success = 0; 81 size_t mask_attempt = 0; 82 } pop; 83 }; 84 85 struct empty_stat { 86 struct { 87 size_t value = 0; 88 size_t count = 0; 89 } push; 90 struct { 91 size_t value = 0; 92 size_t count = 0; 50 93 } pop; 51 94 }; … … 62 105 static_assert(std::is_same<decltype(node_t::_links), _LinksFields_t<node_t>>::value, "Node must have a links field"); 63 106 64 65 107 public: 66 108 relaxed_list(unsigned numLists) 67 : numNonEmpty{0} 68 , lists(new intrusive_queue_t[numLists]) 109 : lists(new intrusive_queue_t[numLists]) 69 110 , numLists(numLists) 70 {} 111 { 112 assertf(7 * 8 * 8 >= numLists, "List currently only supports 448 sublists"); 113 // assert(sizeof(*this) == 128); 114 std::cout << "Constructing Relaxed List with " << numLists << std::endl; 115 116 #ifndef NO_STATS 117 if(head) this->next = head; 118 head = this; 119 #endif 120 } 71 121 72 122 ~relaxed_list() { 123 std::cout << "Destroying Relaxed List" << std::endl; 73 124 lists.reset(); 74 #ifndef NO_STATS75 std::cout << "Difference : "76 << ssize_t(double(intrusive_queue_t::stat::dif.value) / intrusive_queue_t::stat::dif.num ) << " avg\t"77 << intrusive_queue_t::stat::dif.max << "max" << std::endl;78 #endif79 125 } 80 126 … … 84 130 while(true) { 85 131 // Pick a random list 86 inti = tls.rng.next() % numLists;132 unsigned i = tls.rng.next() % numLists; 87 133 88 134 #ifndef NO_STATS … … 93 139 if( !lists[i].lock.try_lock() ) continue; 94 140 141 __attribute__((unused)) int num = numNonEmpty; 142 95 143 // Actually push it 96 lists[i].push(node, numNonEmpty); 144 if(lists[i].push(node)) { 145 numNonEmpty++; 146 size_t qword = i >> 6ull; 147 size_t bit = i & 63ull; 148 assertf((list_mask[qword] & (1ul << bit)) == 0, "Before set %zu:%zu (%u), %zx & %zx", qword, bit, i, list_mask[qword].load(), (1ul << bit)); 149 __attribute__((unused)) bool ret = bts(list_mask[qword], bit); 150 assert(!ret); 151 assertf((list_mask[qword] & (1ul << bit)) != 0, "After set %zu:%zu (%u), %zx & %zx", qword, bit, i, list_mask[qword].load(), (1ul << bit)); 152 } 97 153 assert(numNonEmpty <= (int)numLists); 98 154 … … 102 158 #ifndef NO_STATS 103 159 tls.pick.push.success++; 160 tls.empty.push.value += num; 161 tls.empty.push.count += 1; 104 162 #endif 105 163 return; … … 108 166 109 167 __attribute__((noinline, hot)) node_t * pop() { 110 while(numNonEmpty != 0) { 111 // Pick two lists at random 112 int i = tls.rng.next() % numLists; 113 int j = tls.rng.next() % numLists; 114 115 #ifndef NO_STATS 116 tls.pick.pop.attempt++; 117 #endif 118 119 // Pick the bet list 120 int w = i; 121 if( __builtin_expect(lists[j].ts() != 0, true) ) { 122 w = (lists[i].ts() < lists[j].ts()) ? i : j; 123 } 124 125 auto & list = lists[w]; 126 // If list looks empty retry 127 if( list.ts() == 0 ) continue; 128 129 // If we can't get the lock retry 130 if( !list.lock.try_lock() ) continue; 131 132 // If list is empty, unlock and retry 133 if( list.ts() == 0 ) { 134 list.lock.unlock(); 135 continue; 136 } 137 138 // Actually pop the list 139 auto node = list.pop(numNonEmpty); 140 assert(node); 141 142 // Unlock and return 143 list.lock.unlock(); 144 assert(numNonEmpty >= 0); 145 #ifndef NO_STATS 146 tls.pick.pop.success++; 147 #endif 148 return node; 149 } 168 #if !defined(NO_BITMASK) 169 // for(int r = 0; r < 10 && numNonEmpty != 0; r++) { 170 // // Pick two lists at random 171 // unsigned i = tls.rng.next() % numLists; 172 // unsigned j = tls.rng.next() % numLists; 173 174 // if(auto node = try_pop(i, j)) return node; 175 // } 176 int nnempty; 177 while(0 != (nnempty = numNonEmpty)) { 178 tls.pick.pop.mask_attempt++; 179 unsigned i, j; 180 // if( numLists < 4 || (numLists / nnempty) < 4 ) { 181 // // Pick two lists at random 182 // i = tls.rng.next() % numLists; 183 // j = tls.rng.next() % numLists; 184 // } else 185 { 186 #ifndef NO_STATS 187 // tls.pick.push.mask_attempt++; 188 #endif 189 190 // Pick two lists at random 191 unsigned num = ((numLists - 1) >> 6) + 1; 192 193 unsigned ri = tls.rng.next(); 194 unsigned rj = tls.rng.next(); 195 196 unsigned wdxi = (ri >> 6u) % num; 197 unsigned wdxj = (rj >> 6u) % num; 198 199 size_t maski = list_mask[wdxi].load(std::memory_order_relaxed); 200 size_t maskj = list_mask[wdxj].load(std::memory_order_relaxed); 201 202 if(maski == 0 && maskj == 0) continue; 203 204 unsigned bi = rand_bit(ri, maski); 205 unsigned bj = rand_bit(rj, maskj); 206 207 assertf(bi < 64, "%zu %u", maski, bi); 208 assertf(bj < 64, "%zu %u", maskj, bj); 209 210 i = bi | (wdxi << 6); 211 j = bj | (wdxj << 6); 212 213 assertf(i < numLists, "%u", wdxi << 6); 214 assertf(j < numLists, "%u", wdxj << 6); 215 } 216 217 if(auto node = try_pop(i, j)) return node; 218 } 219 #else 220 while(numNonEmpty != 0) { 221 // Pick two lists at random 222 int i = tls.rng.next() % numLists; 223 int j = tls.rng.next() % numLists; 224 225 if(auto node = try_pop(i, j)) return node; 226 } 227 #endif 150 228 151 229 return nullptr; 152 230 } 231 232 private: 233 node_t * try_pop(unsigned i, unsigned j) { 234 #ifndef NO_STATS 235 tls.pick.pop.attempt++; 236 #endif 237 238 // Pick the bet list 239 int w = i; 240 if( __builtin_expect(lists[j].ts() != 0, true) ) { 241 w = (lists[i].ts() < lists[j].ts()) ? i : j; 242 } 243 244 auto & list = lists[w]; 245 // If list looks empty retry 246 if( list.ts() == 0 ) return nullptr; 247 248 // If we can't get the lock retry 249 if( !list.lock.try_lock() ) return nullptr; 250 251 __attribute__((unused)) int num = numNonEmpty; 252 253 // If list is empty, unlock and retry 254 if( list.ts() == 0 ) { 255 list.lock.unlock(); 256 return nullptr; 257 } 258 259 // Actually pop the list 260 node_t * node; 261 bool emptied; 262 std::tie(node, emptied) = list.pop(); 263 assert(node); 264 265 if(emptied) { 266 numNonEmpty--; 267 size_t qword = w >> 6ull; 268 size_t bit = w & 63ull; 269 assert((list_mask[qword] & (1ul << bit)) != 0); 270 __attribute__((unused)) bool ret = btr(list_mask[qword], bit); 271 assert(ret); 272 assert((list_mask[qword] & (1ul << bit)) == 0); 273 } 274 275 // Unlock and return 276 list.lock.unlock(); 277 assert(numNonEmpty >= 0); 278 #ifndef NO_STATS 279 tls.pick.pop.success++; 280 tls.empty.pop.value += num; 281 tls.empty.pop.count += 1; 282 #endif 283 return node; 284 } 153 285 154 286 private: … … 162 294 struct stat { 163 295 ssize_t diff = 0; 164 165 static struct Dif { 166 ssize_t value = 0; 167 size_t num = 0; 168 ssize_t max = 0; 169 } dif; 296 size_t push = 0; 297 size_t pop = 0; 298 // size_t value = 0; 299 // size_t count = 0; 170 300 }; 171 301 … … 178 308 sentinel_t before; 179 309 sentinel_t after; 180 stat s; 181 310 #ifndef NO_STATS 311 stat s; 312 #endif 313 314 #pragma GCC diagnostic push 315 #pragma GCC diagnostic ignored "-Winvalid-offsetof" 182 316 static constexpr auto fields_offset = offsetof( node_t, _links ); 317 #pragma GCC diagnostic pop 183 318 public: 184 319 intrusive_queue_t() … … 186 321 , after {{ head(), nullptr }} 187 322 { 188 assert((reinterpret_cast<uintptr_t>( head() ) + fields_offset) == reinterpret_cast<uintptr_t>(&before)); 189 assert((reinterpret_cast<uintptr_t>( tail() ) + fields_offset) == reinterpret_cast<uintptr_t>(&after )); 190 assert(head()->_links.prev == nullptr); 191 assert(head()->_links.next == tail() ); 192 assert(tail()->_links.next == nullptr); 193 assert(tail()->_links.prev == head() ); 194 assert(sizeof(*this) == 128); 195 assert((intptr_t(this) % 128) == 0); 196 } 197 198 ~intrusive_queue_t() { 199 #ifndef NO_STATS 200 stat::dif.value+= s.diff; 201 stat::dif.num ++; 202 stat::dif.max = std::abs(stat::dif.max) > std::abs(s.diff) ? stat::dif.max : s.diff; 203 #endif 204 } 323 /* paranoid */ assert((reinterpret_cast<uintptr_t>( head() ) + fields_offset) == reinterpret_cast<uintptr_t>(&before)); 324 /* paranoid */ assert((reinterpret_cast<uintptr_t>( tail() ) + fields_offset) == reinterpret_cast<uintptr_t>(&after )); 325 /* paranoid */ assert(head()->_links.prev == nullptr); 326 /* paranoid */ assert(head()->_links.next == tail() ); 327 /* paranoid */ assert(tail()->_links.next == nullptr); 328 /* paranoid */ assert(tail()->_links.prev == head() ); 329 /* paranoid */ assert(sizeof(*this) == 128); 330 /* paranoid */ assert((intptr_t(this) % 128) == 0); 331 } 332 333 ~intrusive_queue_t() = default; 205 334 206 335 inline node_t * head() const { … … 220 349 } 221 350 222 inline void push(node_t * node, std::atomic_int & nonEmpty) {351 inline bool push(node_t * node) { 223 352 assert(lock); 224 353 assert(node->_links.ts != 0); … … 232 361 prev->_links.next = node; 233 362 tail->_links.prev = node; 363 #ifndef NO_STATS 364 if(enable_stats) { 365 s.diff++; 366 s.push++; 367 } 368 #endif 234 369 if(before._links.ts == 0l) { 235 nonEmpty += 1;236 370 before._links.ts = node->_links.ts; 237 }238 #ifndef NO_STATS239 if(enable_stats) s.diff++;240 #endif241 } 242 243 inline node_t * pop(std::atomic_int & nonEmpty) {371 assert(node->_links.prev == this->head()); 372 return true; 373 } 374 return false; 375 } 376 377 inline std::pair<node_t *, bool> pop() { 244 378 assert(lock); 245 379 node_t * head = this->head(); … … 248 382 node_t * node = head->_links.next; 249 383 node_t * next = node->_links.next; 250 if(node == tail) return nullptr;384 if(node == tail) return {nullptr, false}; 251 385 252 386 head->_links.next = next; 253 387 next->_links.prev = head; 254 388 389 #ifndef NO_STATS 390 if(enable_stats) { 391 s.diff--; 392 s.pop ++; 393 } 394 #endif 255 395 if(next == tail) { 256 396 before._links.ts = 0l; 257 nonEmpty -= 1;397 return {node, true}; 258 398 } 259 399 else { … … 261 401 before._links.ts = next->_links.ts; 262 402 assert(before._links.ts != 0); 263 } 264 #ifndef NO_STATS 265 if(enable_stats) s.diff--; 266 #endif 267 return node; 403 return {node, false}; 404 } 268 405 } 269 406 … … 277 414 278 415 static __attribute__((aligned(128))) thread_local struct TLS { 279 Random rng = { int(rdtscl()) }; 280 pick_stat pick; 416 Random rng = { int(rdtscl()) }; 417 pick_stat pick; 418 empty_stat empty; 281 419 } tls; 282 420 421 public: 422 std::atomic_int numNonEmpty = { 0 }; // number of non-empty lists 423 std::atomic_size_t list_mask[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} }; // which queues are empty 283 424 private: 284 std::atomic_int numNonEmpty; // number of non-empty lists285 425 __attribute__((aligned(64))) std::unique_ptr<intrusive_queue_t []> lists; 286 426 const unsigned numLists; … … 288 428 public: 289 429 static const constexpr size_t sizeof_queue = sizeof(intrusive_queue_t); 430 431 #ifndef NO_STATS 432 static void stats_print(std::ostream & os) { 433 auto it = head; 434 while(it) { 435 it->stats_print_local(os); 436 it = it->next; 437 } 438 } 439 440 static void stats_tls_tally() { 441 global_stats.pick.push.attempt += tls.pick.push.attempt; 442 global_stats.pick.push.success += tls.pick.push.success; 443 global_stats.pick.pop .attempt += tls.pick.pop.attempt; 444 global_stats.pick.pop .success += tls.pick.pop.success; 445 global_stats.pick.pop .mask_attempt += tls.pick.pop.mask_attempt; 446 447 global_stats.qstat.push.value += tls.empty.push.value; 448 global_stats.qstat.push.count += tls.empty.push.count; 449 global_stats.qstat.pop .value += tls.empty.pop .value; 450 global_stats.qstat.pop .count += tls.empty.pop .count; 451 } 452 453 private: 454 static struct GlobalStats { 455 struct { 456 struct { 457 std::atomic_size_t attempt = { 0 }; 458 std::atomic_size_t success = { 0 }; 459 } push; 460 struct { 461 std::atomic_size_t attempt = { 0 }; 462 std::atomic_size_t success = { 0 }; 463 std::atomic_size_t mask_attempt = { 0 }; 464 } pop; 465 } pick; 466 struct { 467 struct { 468 std::atomic_size_t value = { 0 }; 469 std::atomic_size_t count = { 0 }; 470 } push; 471 struct { 472 std::atomic_size_t value = { 0 }; 473 std::atomic_size_t count = { 0 }; 474 } pop; 475 } qstat; 476 } global_stats; 477 478 // Link list of all lists for stats 479 __attribute__((aligned(64))) relaxed_list<node_t> * next = nullptr; 480 481 static relaxed_list<node_t> * head; 482 483 void stats_print_local(std::ostream & os ) { 484 std::cout << "----- Relaxed List Stats -----" << std::endl; 485 { 486 ssize_t diff = 0; 487 size_t num = 0; 488 ssize_t max = 0; 489 490 for(size_t i = 0; i < numLists; i++) { 491 const auto & list = lists[i]; 492 diff+= list.s.diff; 493 num ++; 494 max = std::abs(max) > std::abs(list.s.diff) ? max : list.s.diff; 495 os << "Local Q ops : " << (list.s.push + list.s.pop) << "(" << list.s.push << "i, " << list.s.pop << "o)\n"; 496 } 497 498 os << "Difference : " << ssize_t(double(diff) / num ) << " avg\t" << max << "max" << std::endl; 499 } 500 501 const auto & global = global_stats; 502 503 double push_sur = (100.0 * double(global.pick.push.success) / global.pick.push.attempt); 504 double pop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .attempt); 505 double mpop_sur = (100.0 * double(global.pick.pop .success) / global.pick.pop .mask_attempt); 506 507 os << "Push Pick % : " << push_sur << "(" << global.pick.push.success << " / " << global.pick.push.attempt << ")\n"; 508 os << "Pop Pick % : " << pop_sur << "(" << global.pick.pop .success << " / " << global.pick.pop .attempt << ")\n"; 509 os << "TryPop Pick % : " << mpop_sur << "(" << global.pick.pop .success << " / " << global.pick.pop .mask_attempt << ")\n"; 510 511 double avgQ_push = double(global.qstat.push.value) / global.qstat.push.count; 512 double avgQ_pop = double(global.qstat.pop .value) / global.qstat.pop .count; 513 double avgQ = double(global.qstat.push.value + global.qstat.pop .value) / (global.qstat.push.count + global.qstat.pop .count); 514 os << "Push Avg Qs : " << avgQ_push << " (" << global.qstat.push.count << "ops)\n"; 515 os << "Pop Avg Qs : " << avgQ_pop << " (" << global.qstat.pop .count << "ops)\n"; 516 os << "Global Avg Qs : " << avgQ << " (" << (global.qstat.push.count + global.qstat.pop .count) << "ops)\n"; 517 } 518 #endif 290 519 }; -
doc/theses/thierry_delisle_PhD/code/utils.hpp
r8c50aed ra505021 10 10 #include <unistd.h> 11 11 #include <sys/sysinfo.h> 12 13 #include <x86intrin.h> 12 14 13 15 // Barrier from … … 56 58 } 57 59 58 void affinity(int tid) {60 static inline void affinity(int tid) { 59 61 static int cpus = get_nprocs(); 60 62 … … 70 72 71 73 static const constexpr std::size_t cache_line_size = 64; 72 void check_cache_line_size() {74 static inline void check_cache_line_size() { 73 75 std::cout << "Checking cache line size" << std::endl; 74 76 const std::string cache_file = "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"; … … 103 105 return std::chrono::duration_cast<std::chrono::duration<T, Ratio>>(std::chrono::duration<T>(seconds)).count(); 104 106 } 107 108 static inline unsigned rand_bit(unsigned rnum, size_t mask) { 109 unsigned bit = mask ? rnum % __builtin_popcountl(mask) : 0; 110 #if !defined(__BMI2__) 111 uint64_t v = mask; // Input value to find position with rank r. 112 unsigned int r = bit + 1;// Input: bit's desired rank [1-64]. 113 unsigned int s; // Output: Resulting position of bit with rank r [1-64] 114 uint64_t a, b, c, d; // Intermediate temporaries for bit count. 115 unsigned int t; // Bit count temporary. 116 117 // Do a normal parallel bit count for a 64-bit integer, 118 // but store all intermediate steps. 119 a = v - ((v >> 1) & ~0UL/3); 120 b = (a & ~0UL/5) + ((a >> 2) & ~0UL/5); 121 c = (b + (b >> 4)) & ~0UL/0x11; 122 d = (c + (c >> 8)) & ~0UL/0x101; 123 124 125 t = (d >> 32) + (d >> 48); 126 // Now do branchless select! 127 s = 64; 128 s -= ((t - r) & 256) >> 3; r -= (t & ((t - r) >> 8)); 129 t = (d >> (s - 16)) & 0xff; 130 s -= ((t - r) & 256) >> 4; r -= (t & ((t - r) >> 8)); 131 t = (c >> (s - 8)) & 0xf; 132 s -= ((t - r) & 256) >> 5; r -= (t & ((t - r) >> 8)); 133 t = (b >> (s - 4)) & 0x7; 134 s -= ((t - r) & 256) >> 6; r -= (t & ((t - r) >> 8)); 135 t = (a >> (s - 2)) & 0x3; 136 s -= ((t - r) & 256) >> 7; r -= (t & ((t - r) >> 8)); 137 t = (v >> (s - 1)) & 0x1; 138 s -= ((t - r) & 256) >> 8; 139 return s - 1; 140 #else 141 uint64_t picked = _pdep_u64(1ul << bit, mask); 142 return picked ? __builtin_ctzl(picked) : 0; 143 #endif 144 } -
driver/cfa.cc
r8c50aed ra505021 411 411 args[nargs++] = "-lcfathread"; 412 412 args[nargs++] = "-Wl,--pop-state"; 413 args[nargs++] = "-Wl,--push-state,--no-as-needed"; 413 414 args[nargs++] = "-lcfa"; 415 args[nargs++] = "-Wl,--pop-state"; 414 416 args[nargs++] = "-pthread"; 415 417 args[nargs++] = "-ldl"; -
libcfa/prelude/Makefile.am
r8c50aed ra505021 11 11 ## Created On : Sun May 31 08:54:01 2015 12 12 ## Last Modified By : Peter A. Buhr 13 ## Last Modified On : Wed Dec 14 15:00:35 201614 ## Update Count : 20 513 ## Last Modified On : Mon Feb 3 21:27:18 2020 14 ## Update Count : 208 15 15 ############################################################################### 16 16 … … 36 36 extras.cf : ${srcdir}/extras.regx ${srcdir}/extras.c 37 37 ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -f ${srcdir}/extras.regx > extras.cf 38 ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -zo -f ${srcdir}/extras.regx2 | tr '\0' '\n' >> extras.cf 38 39 39 40 # create forward declarations for gcc builtins -
libcfa/prelude/Makefile.in
r8c50aed ra505021 1 # Makefile.in generated by automake 1.1 5from Makefile.am.1 # Makefile.in generated by automake 1.16.1 from Makefile.am. 2 2 # @configure_input@ 3 3 4 # Copyright (C) 1994-201 4Free Software Foundation, Inc.4 # Copyright (C) 1994-2018 Free Software Foundation, Inc. 5 5 6 6 # This Makefile.in is free software; the Free Software Foundation … … 331 331 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 332 332 *) \ 333 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__ depfiles_maybe)'; \334 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__ depfiles_maybe);; \333 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ 334 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ 335 335 esac; 336 336 … … 377 377 378 378 379 distdir: $(DISTFILES) 379 distdir: $(BUILT_SOURCES) 380 $(MAKE) $(AM_MAKEFLAGS) distdir-am 381 382 distdir-am: $(DISTFILES) 380 383 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 381 384 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ … … 540 543 extras.cf : ${srcdir}/extras.regx ${srcdir}/extras.c 541 544 ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -f ${srcdir}/extras.regx > extras.cf 545 ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -zo -f ${srcdir}/extras.regx2 | tr '\0' '\n' >> extras.cf 542 546 543 547 # create forward declarations for gcc builtins -
libcfa/prelude/extras.regx
r8c50aed ra505021 24 24 typedef.* char32_t; 25 25 typedef.* wchar_t; 26 extern.*\*malloc\(.*\).*27 extern.* free\(.*\).*28 extern.* exit\(.*\).*29 extern.* atexit\(.*\).*30 extern.* abort\(.*\).*31 extern.* printf\(.*\).* -
libcfa/prelude/prototypes.awk
r8c50aed ra505021 10 10 # Created On : Sat May 16 07:57:37 2015 11 11 # Last Modified By : Peter A. Buhr 12 # Last Modified On : Thu Jun 6 20:46:28 201913 # Update Count : 3 412 # Last Modified On : Sat Feb 8 09:46:58 2020 13 # Update Count : 36 14 14 # 15 15 … … 17 17 18 18 BEGIN { 19 19 FS = "[( )]" 20 20 # order so string search is longest string 21 21 i=-1 … … 84 84 85 85 /BT_FN/ { 86 for (i = 1; i <= NF; i ++) {87 if( match($i, "BT_FN") != 0 ) {88 prototypes[$i] = $i89 86 for (i = 1; i <= NF; i += 1 ) { 87 if ( match($i, "BT_FN") != 0 ) { 88 prototypes[$i] = $i 89 } 90 90 } 91 91 } 92 92 93 93 END { … … 103 103 104 104 for ( prototype in prototypes ) { 105 106 107 continue108 105 # printf( "//\"%s\"\n", prototype ) 106 if ( index( "BT_LAST", prototype ) == 1 ) { 107 continue 108 } # if 109 109 110 110 printf( "#define %s(NAME) FUNC_SIMPLE(", prototype ) 111 111 112 113 printf( "\n********** BAD MACRO NAME \"%s\" **********\n", prototype )114 exit 0115 112 if ( sub( "BT_FN_", "", prototype ) == 0 ) { 113 printf( "\n********** BAD MACRO NAME \"%s\" **********\n", prototype ) 114 exit 0 115 } # if 116 116 117 # generate function return type as macro 118 for ( t = 0; t < N; t += 1 ) { # find longest match 119 type = types[t]; 120 if ( index( prototype, type ) == 1 ) { # found match 121 printf( "BT_%s, NAME", type ) 122 sub( type, "", prototype ) 123 break; 117 # generate function return type as macro 118 for ( t = 0; t < N; t += 1 ) { # find longest match 119 type = types[t]; 120 if ( index( prototype, type ) == 1 ) { # found match 121 printf( "BT_%s, NAME", type ) 122 sub( type, "", prototype ) 123 break; 124 } # if 125 } # for 126 127 # generate function parameter types as macro 128 if ( index( prototype, "VAR" ) != 2 ) { # C-style empty parameters ? 129 for ( p = 0; length( prototype ) > 0; p += 1 ) { # until all parameters types are removed 130 sub( "_", "", prototype) # remove "_" 131 printf( ", ", type ) 132 temp = prototype 133 for ( t = 0; t < N; t += 1 ) { # find longest match 134 type = types[t]; 135 if ( index( prototype, type ) == 1 ) { # found match 136 printf( "BT_%s", type ) 137 sub( type, "", prototype ) 138 break; 139 } # if 140 } # for 141 if ( temp == prototype ) { # no match found for parameter in macro table 142 printf( "\n********** MISSING TYPE \"%s\" **********\n", prototype ) 143 exit 0 144 } # if 145 } # for 124 146 } # if 125 } # for 126 127 # generate function parameter types as macro 128 if ( index( prototype, "VAR" ) != 2 ) { # C-style empty parameters ? 129 for ( p = 0; length( prototype ) > 0; p += 1 ) { # until all parameters types are removed 130 sub( "_", "", prototype) # remove "_" 131 printf( ", ", type ) 132 temp = prototype 133 for ( t = 0; t < N; t += 1 ) { # find longest match 134 type = types[t]; 135 if ( index( prototype, type ) == 1 ) { # found match 136 printf( "BT_%s", type ) 137 sub( type, "", prototype ) 138 break; 139 } # if 140 } # for 141 if ( temp == prototype ) { # no match found for parameter in macro table 142 printf( "\n********** MISSING TYPE \"%s\" **********\n", prototype ) 143 exit 0 144 } # if 145 } # for 146 } # if 147 printf( ")\n" ) 147 printf( ")\n" ) 148 148 } # for 149 149 -
libcfa/src/assert.cfa
r8c50aed ra505021 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Nov 21 17:09:26 201913 // Update Count : 512 // Last Modified On : Tue Feb 4 13:00:18 2020 13 // Update Count : 6 14 14 // 15 15 … … 26 26 27 27 // called by macro assert in assert.h 28 void __assert_fail( const char *assertion, const char *file, unsigned int line, const char *function) {28 void __assert_fail( const char assertion[], const char file[], unsigned int line, const char function[] ) { 29 29 __cfaabi_bits_print_safe( STDERR_FILENO, CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file ); 30 30 abort(); … … 32 32 33 33 // called by macro assertf 34 void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) {34 void __assert_fail_f( const char assertion[], const char file[], unsigned int line, const char function[], const char fmt[], ... ) { 35 35 __cfaabi_bits_acquire(); 36 36 __cfaabi_bits_print_nolock( STDERR_FILENO, CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file ); -
libcfa/src/bits/debug.cfa
r8c50aed ra505021 10 10 // Created On : Thu Mar 30 12:30:01 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Nov 21 17:16:30 201913 // Update Count : 1 012 // Last Modified On : Tue Feb 4 13:03:16 2020 13 // Update Count : 11 14 14 // 15 15 … … 27 27 28 28 extern "C" { 29 30 void __cfaabi_bits_write( int fd, const char *in_buffer, int len ) { 29 void __cfaabi_bits_write( int fd, const char in_buffer[], int len ) { 31 30 // ensure all data is written 32 31 for ( int count = 0, retcode; count < len; count += retcode ) { -
libcfa/src/bits/debug.hfa
r8c50aed ra505021 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Nov 21 17:06:58 201913 // Update Count : 812 // Last Modified On : Tue Feb 4 12:29:21 2020 13 // Update Count : 9 14 14 // 15 15 … … 21 21 #define __cfaabi_dbg_ctx __PRETTY_FUNCTION__ 22 22 #define __cfaabi_dbg_ctx2 , __PRETTY_FUNCTION__ 23 #define __cfaabi_dbg_ctx_param const char * caller24 #define __cfaabi_dbg_ctx_param2 , const char * caller23 #define __cfaabi_dbg_ctx_param const char caller[] 24 #define __cfaabi_dbg_ctx_param2 , const char caller[] 25 25 #else 26 26 #define __cfaabi_dbg_debug_do(...) … … 38 38 #include <stdio.h> 39 39 40 extern void __cfaabi_bits_write( int fd, const char *buffer, int len );40 extern void __cfaabi_bits_write( int fd, const char buffer[], int len ); 41 41 extern void __cfaabi_bits_acquire(); 42 42 extern void __cfaabi_bits_release(); -
libcfa/src/bits/locks.hfa
r8c50aed ra505021 10 10 // Created On : Tue Oct 31 15:14:38 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 11 15:42:24 201813 // Update Count : 1 012 // Last Modified On : Tue Feb 4 13:03:19 2020 13 // Update Count : 11 14 14 // 15 15 … … 54 54 55 55 #ifdef __CFA_DEBUG__ 56 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name);56 void __cfaabi_dbg_record(__spinlock_t & this, const char prev_name[]); 57 57 #else 58 58 #define __cfaabi_dbg_record(x, y) -
libcfa/src/concurrency/coroutine.cfa
r8c50aed ra505021 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Dec 5 14:37:29 201913 // Update Count : 1 512 // Last Modified On : Tue Feb 4 12:29:25 2020 13 // Update Count : 16 14 14 // 15 15 … … 89 89 } 90 90 91 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {91 void ?{}( coroutine_desc & this, const char name[], void * storage, size_t storageSize ) with( this ) { 92 92 (this.context){0p, 0p}; 93 93 (this.stack){storage, storageSize}; -
libcfa/src/concurrency/coroutine.hfa
r8c50aed ra505021 10 10 // Created On : Mon Nov 28 12:27:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 3 22:47:58 201913 // Update Count : 1 012 // Last Modified On : Tue Feb 4 12:29:26 2020 13 // Update Count : 11 14 14 // 15 15 … … 35 35 // void ^?{}( coStack_t & this ); 36 36 37 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize );37 void ?{}( coroutine_desc & this, const char name[], void * storage, size_t storageSize ); 38 38 void ^?{}( coroutine_desc & this ); 39 39 … … 41 41 static inline void ?{}( coroutine_desc & this, size_t stackSize) { this{ "Anonymous Coroutine", 0p, stackSize }; } 42 42 static inline void ?{}( coroutine_desc & this, void * storage, size_t storageSize ) { this{ "Anonymous Coroutine", storage, storageSize }; } 43 static inline void ?{}( coroutine_desc & this, const char * name) { this{ name, 0p, 0 }; }44 static inline void ?{}( coroutine_desc & this, const char * name, size_t stackSize ) { this{ name, 0p, stackSize }; }43 static inline void ?{}( coroutine_desc & this, const char name[]) { this{ name, 0p, 0 }; } 44 static inline void ?{}( coroutine_desc & this, const char name[], size_t stackSize ) { this{ name, 0p, stackSize }; } 45 45 46 46 //----------------------------------------------------------------------------- -
libcfa/src/concurrency/kernel.cfa
r8c50aed ra505021 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Jan 30 22:55:50202013 // Update Count : 5 612 // Last Modified On : Tue Feb 4 13:03:15 2020 13 // Update Count : 58 14 14 // 15 15 … … 210 210 static void * CtxInvokeProcessor(void * arg); 211 211 212 void ?{}(processor & this, const char * name, cluster & cltr) with( this ) {212 void ?{}(processor & this, const char name[], cluster & cltr) with( this ) { 213 213 this.name = name; 214 214 this.cltr = &cltr; … … 244 244 } 245 245 246 void ?{}(cluster & this, const char * name, Duration preemption_rate) with( this ) {246 void ?{}(cluster & this, const char name[], Duration preemption_rate) with( this ) { 247 247 this.name = name; 248 248 this.preemption_rate = preemption_rate; … … 459 459 } 460 460 461 static void Abort( int ret, const char * func) {461 static void Abort( int ret, const char func[] ) { 462 462 if ( ret ) { // pthread routines return errno values 463 463 abort( "%s : internal error, error(%d) %s.", func, ret, strerror( ret ) ); … … 960 960 __cfaabi_dbg_debug_do( 961 961 extern "C" { 962 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {962 void __cfaabi_dbg_record(__spinlock_t & this, const char prev_name[]) { 963 963 this.prev_name = prev_name; 964 964 this.prev_thrd = kernelTLS.this_thread; -
libcfa/src/concurrency/kernel.hfa
r8c50aed ra505021 10 10 // Created On : Tue Jan 17 12:27:26 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Dec 4 07:54:51 201913 // Update Count : 1812 // Last Modified On : Tue Feb 4 12:29:26 2020 13 // Update Count : 22 14 14 // 15 15 … … 101 101 }; 102 102 103 void ?{}(processor & this, const char * name, struct cluster & cltr);103 void ?{}(processor & this, const char name[], struct cluster & cltr); 104 104 void ^?{}(processor & this); 105 105 106 106 static inline void ?{}(processor & this) { this{ "Anonymous Processor", *mainCluster}; } 107 107 static inline void ?{}(processor & this, struct cluster & cltr) { this{ "Anonymous Processor", cltr}; } 108 static inline void ?{}(processor & this, const char * name) { this{name, *mainCluster }; }108 static inline void ?{}(processor & this, const char name[]) { this{name, *mainCluster }; } 109 109 110 110 static inline [processor *&, processor *& ] __get( processor & this ) /*__attribute__((const))*/ { return this.node.[next, prev]; } … … 144 144 extern Duration default_preemption(); 145 145 146 void ?{} (cluster & this, const char * name, Duration preemption_rate);146 void ?{} (cluster & this, const char name[], Duration preemption_rate); 147 147 void ^?{}(cluster & this); 148 148 149 149 static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption()}; } 150 150 static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; } 151 static inline void ?{} (cluster & this, const char * name) { this{name, default_preemption()}; }151 static inline void ?{} (cluster & this, const char name[]) { this{name, default_preemption()}; } 152 152 153 153 static inline [cluster *&, cluster *& ] __get( cluster & this ) /*__attribute__((const))*/ { return this.node.[next, prev]; } -
libcfa/src/exception.c
r8c50aed ra505021 248 248 } 249 249 250 #if defined(PIC) 251 #warning Exceptions not yet supported when using Position-Independent Code 252 __attribute__((noinline)) 253 void __cfaabi_ehm__try_terminate(void (*try_block)(), 254 void (*catch_block)(int index, exception_t * except), 255 __attribute__((unused)) int (*match_block)(exception_t * except)) { 256 abort(); 257 } 258 #else // PIC 250 #pragma GCC push_options 251 #pragma GCC optimize("O0") 252 259 253 // This is our personality routine. For every stack frame annotated with 260 254 // ".cfi_personality 0x3,__gcfa_personality_v0" this function will be called twice when unwinding. … … 431 425 432 426 // Setup the personality routine and exception table. 427 #ifdef __PIC__ 428 asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0"); 429 asm volatile (".cfi_lsda 0x1b, .LLSDACFA2"); 430 #else 433 431 asm volatile (".cfi_personality 0x3,__gcfa_personality_v0"); 434 432 asm volatile (".cfi_lsda 0x3, .LLSDACFA2"); 433 #endif 435 434 436 435 // Label which defines the start of the area for which the handler is setup. … … 464 463 // have a single call to the try routine. 465 464 465 #ifdef __PIC__ 466 #if defined( __i386 ) || defined( __x86_64 ) 467 asm ( 468 // HEADER 469 ".LFECFA1:\n" 470 " .globl __gcfa_personality_v0\n" 471 " .section .gcc_except_table,\"a\",@progbits\n" 472 // TABLE HEADER (important field is the BODY length at the end) 473 ".LLSDACFA2:\n" 474 " .byte 0xff\n" 475 " .byte 0xff\n" 476 " .byte 0x1\n" 477 " .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n" 478 // BODY (language specific data) 479 // This uses language specific data and can be modified arbitrarily 480 // We use handled area offset, handled area length, 481 // handler landing pad offset and 1 (action code, gcc seems to use 0). 482 ".LLSDACSBCFA2:\n" 483 " .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n" 484 " .uleb128 .TRYEND-.TRYSTART\n" 485 " .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n" 486 " .uleb128 1\n" 487 ".LLSDACSECFA2:\n" 488 // TABLE FOOTER 489 " .text\n" 490 " .size __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n" 491 ); 492 493 // Somehow this piece of helps with the resolution of debug symbols. 494 __attribute__((unused)) static const int dummy = 0; 495 496 asm ( 497 // Add a hidden symbol which points at the function. 498 " .hidden CFA.ref.__gcfa_personality_v0\n" 499 " .weak CFA.ref.__gcfa_personality_v0\n" 500 // No clue what this does specifically 501 " .section .data.rel.local.CFA.ref.__gcfa_personality_v0,\"awG\",@progbits,CFA.ref.__gcfa_personality_v0,comdat\n" 502 " .align 8\n" 503 " .type CFA.ref.__gcfa_personality_v0, @object\n" 504 " .size CFA.ref.__gcfa_personality_v0, 8\n" 505 "CFA.ref.__gcfa_personality_v0:\n" 506 #if defined( __x86_64 ) 507 " .quad __gcfa_personality_v0\n" 508 #else // then __i386 509 " .long __gcfa_personality_v0\n" 510 #endif 511 ); 512 #else 513 #error Exception Handling: unknown architecture for position independent code. 514 #endif // __i386 || __x86_64 515 #else // __PIC__ 466 516 #if defined( __i386 ) || defined( __x86_64 ) 467 517 asm ( … … 491 541 " .size __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n" 492 542 " .ident \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n" 493 //" .section .note.GNU-stack,\"x\",@progbits\n"543 " .section .note.GNU-stack,\"x\",@progbits\n" 494 544 ); 545 #else 546 #error Exception Handling: unknown architecture for position dependent code. 495 547 #endif // __i386 || __x86_64 496 #endif // PIC 548 #endif // __PIC__ 549 550 #pragma GCC pop_options -
libcfa/src/fstream.cfa
r8c50aed ra505021 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Nov 29 06:56:46 201913 // Update Count : 3 5512 // Last Modified On : Fri Feb 7 19:01:01 2020 13 // Update Count : 363 14 14 // 15 15 … … 32 32 33 33 void ?{}( ofstream & os, void * file ) { 34 os.file = file; 35 os.sepDefault = true; 36 os.sepOnOff = false; 37 os.nlOnOff = true; 38 os.prt = false; 39 os.sawNL = false; 34 os.$file = file; 35 os.$sepDefault = true; 36 os.$sepOnOff = false; 37 os.$nlOnOff = true; 38 os.$prt = false; 39 os.$sawNL = false; 40 $sepSetCur( os, sepGet( os ) ); 40 41 sepSet( os, " " ); 41 sepSetCur( os, sepGet( os ) );42 42 sepSetTuple( os, ", " ); 43 43 } // ?{} 44 44 45 45 // private 46 bool sepPrt( ofstream & os ) { setNL( os, false ); return os.sepOnOff; }47 void sepReset( ofstream & os ) { os.sepOnOff = os.sepDefault; }48 void sepReset( ofstream & os, bool reset ) { os.sepDefault = reset; os.sepOnOff = os.sepDefault; }49 const char * sepGetCur( ofstream & os ) { return os.sepCur; }50 void sepSetCur( ofstream & os, const char * sepCur ) { os.sepCur = sepCur; }51 bool getNL( ofstream & os ) { return os.sawNL; }52 void setNL( ofstream & os, bool state ) { os.sawNL = state; }53 bool getANL( ofstream & os ) { return os.nlOnOff; }54 bool getPrt( ofstream & os ) { return os.prt; }55 void setPrt( ofstream & os, bool state ) { os.prt = state; }46 bool $sepPrt( ofstream & os ) { $setNL( os, false ); return os.$sepOnOff; } 47 void $sepReset( ofstream & os ) { os.$sepOnOff = os.$sepDefault; } 48 void $sepReset( ofstream & os, bool reset ) { os.$sepDefault = reset; os.$sepOnOff = os.$sepDefault; } 49 const char * $sepGetCur( ofstream & os ) { return os.$sepCur; } 50 void $sepSetCur( ofstream & os, const char sepCur[] ) { os.$sepCur = sepCur; } 51 bool $getNL( ofstream & os ) { return os.$sawNL; } 52 void $setNL( ofstream & os, bool state ) { os.$sawNL = state; } 53 bool $getANL( ofstream & os ) { return os.$nlOnOff; } 54 bool $getPrt( ofstream & os ) { return os.$prt; } 55 void $setPrt( ofstream & os, bool state ) { os.$prt = state; } 56 56 57 57 // public 58 void ?{}( ofstream & os ) { os. file = 0; }59 60 void ?{}( ofstream & os, const char * name, const char * mode) {58 void ?{}( ofstream & os ) { os.$file = 0p; } 59 60 void ?{}( ofstream & os, const char name[], const char mode[] ) { 61 61 open( os, name, mode ); 62 62 } // ?{} 63 63 64 void ?{}( ofstream & os, const char * name) {64 void ?{}( ofstream & os, const char name[] ) { 65 65 open( os, name, "w" ); 66 66 } // ?{} … … 70 70 } // ^?{} 71 71 72 void sepOn( ofstream & os ) { os. sepOnOff = !getNL( os ); }73 void sepOff( ofstream & os ) { os. sepOnOff = false; }72 void sepOn( ofstream & os ) { os.$sepOnOff = ! $getNL( os ); } 73 void sepOff( ofstream & os ) { os.$sepOnOff = false; } 74 74 75 75 bool sepDisable( ofstream & os ) { 76 bool temp = os. sepDefault;77 os. sepDefault = false;78 sepReset( os );76 bool temp = os.$sepDefault; 77 os.$sepDefault = false; 78 $sepReset( os ); 79 79 return temp; 80 80 } // sepDisable 81 81 82 82 bool sepEnable( ofstream & os ) { 83 bool temp = os. sepDefault;84 os. sepDefault = true;85 if ( os. sepOnOff ) sepReset( os );// start of line ?83 bool temp = os.$sepDefault; 84 os.$sepDefault = true; 85 if ( os.$sepOnOff ) $sepReset( os ); // start of line ? 86 86 return temp; 87 87 } // sepEnable 88 88 89 void nlOn( ofstream & os ) { os. nlOnOff = true; }90 void nlOff( ofstream & os ) { os. nlOnOff = false; }91 92 const char * sepGet( ofstream & os ) { return os. separator; }93 void sepSet( ofstream & os, const char * s) {89 void nlOn( ofstream & os ) { os.$nlOnOff = true; } 90 void nlOff( ofstream & os ) { os.$nlOnOff = false; } 91 92 const char * sepGet( ofstream & os ) { return os.$separator; } 93 void sepSet( ofstream & os, const char s[] ) { 94 94 assert( s ); 95 strncpy( os. separator, s, sepSize - 1 );96 os. separator[sepSize - 1] = '\0';95 strncpy( os.$separator, s, sepSize - 1 ); 96 os.$separator[sepSize - 1] = '\0'; 97 97 } // sepSet 98 98 99 const char * sepGetTuple( ofstream & os ) { return os. tupleSeparator; }100 void sepSetTuple( ofstream & os, const char * s) {99 const char * sepGetTuple( ofstream & os ) { return os.$tupleSeparator; } 100 void sepSetTuple( ofstream & os, const char s[] ) { 101 101 assert( s ); 102 strncpy( os. tupleSeparator, s, sepSize - 1 );103 os. tupleSeparator[sepSize - 1] = '\0';102 strncpy( os.$tupleSeparator, s, sepSize - 1 ); 103 os.$tupleSeparator[sepSize - 1] = '\0'; 104 104 } // sepSet 105 105 106 106 void ends( ofstream & os ) { 107 if ( getANL( os ) ) nl( os );108 else setPrt( os, false ); // turn off107 if ( $getANL( os ) ) nl( os ); 108 else $setPrt( os, false ); // turn off 109 109 if ( &os == &exit ) exit( EXIT_FAILURE ); 110 110 if ( &os == &abort ) abort(); … … 112 112 113 113 int fail( ofstream & os ) { 114 return os. file == 0 || ferror( (FILE *)(os.file) );114 return os.$file == 0 || ferror( (FILE *)(os.$file) ); 115 115 } // fail 116 116 117 117 int flush( ofstream & os ) { 118 return fflush( (FILE *)(os. file) );118 return fflush( (FILE *)(os.$file) ); 119 119 } // flush 120 120 121 void open( ofstream & os, const char * name, const char * mode) {121 void open( ofstream & os, const char name[], const char mode[] ) { 122 122 FILE * file = fopen( name, mode ); 123 123 #ifdef __CFA_DEBUG__ 124 if ( file == 0 ) {124 if ( file == 0p ) { 125 125 abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno ); 126 126 } // if … … 129 129 } // open 130 130 131 void open( ofstream & os, const char * name) {131 void open( ofstream & os, const char name[] ) { 132 132 open( os, name, "w" ); 133 133 } // open 134 134 135 135 void close( ofstream & os ) { 136 if ( (FILE *)(os. file) == stdout || (FILE *)(os.file) == stderr ) return;137 138 if ( fclose( (FILE *)(os. file) ) == EOF ) {136 if ( (FILE *)(os.$file) == stdout || (FILE *)(os.$file) == stderr ) return; 137 138 if ( fclose( (FILE *)(os.$file) ) == EOF ) { 139 139 abort | IO_MSG "close output" | nl | strerror( errno ); 140 140 } // if 141 141 } // close 142 142 143 ofstream & write( ofstream & os, const char * data, size_t size ) {143 ofstream & write( ofstream & os, const char data[], size_t size ) { 144 144 if ( fail( os ) ) { 145 145 abort | IO_MSG "attempt write I/O on failed stream"; 146 146 } // if 147 147 148 if ( fwrite( data, 1, size, (FILE *)(os. file) ) != size ) {148 if ( fwrite( data, 1, size, (FILE *)(os.$file) ) != size ) { 149 149 abort | IO_MSG "write" | nl | strerror( errno ); 150 150 } // if … … 155 155 va_list args; 156 156 va_start( args, format ); 157 int len = vfprintf( (FILE *)(os. file), format, args );157 int len = vfprintf( (FILE *)(os.$file), format, args ); 158 158 if ( len == EOF ) { 159 if ( ferror( (FILE *)(os. file) ) ) {159 if ( ferror( (FILE *)(os.$file) ) ) { 160 160 abort | IO_MSG "invalid write"; 161 161 } // if … … 163 163 va_end( args ); 164 164 165 setPrt( os, true );// called in output cascade166 sepReset( os );// reset separator165 $setPrt( os, true ); // called in output cascade 166 $sepReset( os ); // reset separator 167 167 return len; 168 168 } // fmt … … 184 184 // private 185 185 void ?{}( ifstream & is, void * file ) { 186 is. file = file;187 is. nlOnOff = false;186 is.$file = file; 187 is.$nlOnOff = false; 188 188 } // ?{} 189 189 190 190 // public 191 void ?{}( ifstream & is ) { is.file = 0; }192 193 void ?{}( ifstream & is, const char * name, const char * mode) {191 void ?{}( ifstream & is ) { is.$file = 0p; } 192 193 void ?{}( ifstream & is, const char name[], const char mode[] ) { 194 194 open( is, name, mode ); 195 195 } // ?{} 196 196 197 void ?{}( ifstream & is, const char * name) {197 void ?{}( ifstream & is, const char name[] ) { 198 198 open( is, name, "r" ); 199 199 } // ?{} … … 203 203 } // ^?{} 204 204 205 void nlOn( ifstream & os ) { os. nlOnOff = true; }206 void nlOff( ifstream & os ) { os. nlOnOff = false; }207 bool getANL( ifstream & os ) { return os. nlOnOff; }205 void nlOn( ifstream & os ) { os.$nlOnOff = true; } 206 void nlOff( ifstream & os ) { os.$nlOnOff = false; } 207 bool getANL( ifstream & os ) { return os.$nlOnOff; } 208 208 209 209 int fail( ifstream & is ) { 210 return is. file == 0 || ferror( (FILE *)(is.file) );210 return is.$file == 0p || ferror( (FILE *)(is.$file) ); 211 211 } // fail 212 212 213 213 int eof( ifstream & is ) { 214 return feof( (FILE *)(is. file) );214 return feof( (FILE *)(is.$file) ); 215 215 } // eof 216 216 217 void open( ifstream & is, const char * name, const char * mode) {217 void open( ifstream & is, const char name[], const char mode[] ) { 218 218 FILE * file = fopen( name, mode ); 219 219 #ifdef __CFA_DEBUG__ 220 if ( file == 0 ) {220 if ( file == 0p ) { 221 221 abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno ); 222 222 } // if 223 223 #endif // __CFA_DEBUG__ 224 is. file = file;225 } // open 226 227 void open( ifstream & is, const char * name) {224 is.$file = file; 225 } // open 226 227 void open( ifstream & is, const char name[] ) { 228 228 open( is, name, "r" ); 229 229 } // open 230 230 231 231 void close( ifstream & is ) { 232 if ( (FILE *)(is. file) == stdin ) return;233 234 if ( fclose( (FILE *)(is. file) ) == EOF ) {232 if ( (FILE *)(is.$file) == stdin ) return; 233 234 if ( fclose( (FILE *)(is.$file) ) == EOF ) { 235 235 abort | IO_MSG "close input" | nl | strerror( errno ); 236 236 } // if … … 242 242 } // if 243 243 244 if ( fread( data, size, 1, (FILE *)(is. file) ) == 0 ) {244 if ( fread( data, size, 1, (FILE *)(is.$file) ) == 0 ) { 245 245 abort | IO_MSG "read" | nl | strerror( errno ); 246 246 } // if … … 253 253 } // if 254 254 255 if ( ungetc( c, (FILE *)(is. file) ) == EOF ) {255 if ( ungetc( c, (FILE *)(is.$file) ) == EOF ) { 256 256 abort | IO_MSG "ungetc" | nl | strerror( errno ); 257 257 } // if … … 263 263 264 264 va_start( args, format ); 265 int len = vfscanf( (FILE *)(is. file), format, args );265 int len = vfscanf( (FILE *)(is.$file), format, args ); 266 266 if ( len == EOF ) { 267 if ( ferror( (FILE *)(is. file) ) ) {267 if ( ferror( (FILE *)(is.$file) ) ) { 268 268 abort | IO_MSG "invalid read"; 269 269 } // if -
libcfa/src/fstream.hfa
r8c50aed ra505021 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Nov 29 06:56:02 201913 // Update Count : 1 6812 // Last Modified On : Mon Feb 17 08:29:23 2020 13 // Update Count : 175 14 14 // 15 15 … … 24 24 enum { sepSize = 16 }; 25 25 struct ofstream { 26 void * file;27 bool sepDefault;28 bool sepOnOff;29 bool nlOnOff;30 bool prt; // print text31 bool sawNL;32 const char * sepCur;33 char separator[sepSize];34 char tupleSeparator[sepSize];26 void * $file; 27 bool $sepDefault; 28 bool $sepOnOff; 29 bool $nlOnOff; 30 bool $prt; // print text 31 bool $sawNL; 32 const char * $sepCur; 33 char $separator[sepSize]; 34 char $tupleSeparator[sepSize]; 35 35 }; // ofstream 36 36 37 37 // private 38 bool sepPrt( ofstream & );39 void sepReset( ofstream & );40 void sepReset( ofstream &, bool );41 const char * sepGetCur( ofstream & );42 void sepSetCur( ofstream &, const char *);43 bool getNL( ofstream & );44 void setNL( ofstream &, bool );45 bool getANL( ofstream & );46 bool getPrt( ofstream & );47 void setPrt( ofstream &, bool );38 bool $sepPrt( ofstream & ); 39 void $sepReset( ofstream & ); 40 void $sepReset( ofstream &, bool ); 41 const char * $sepGetCur( ofstream & ); 42 void $sepSetCur( ofstream &, const char [] ); 43 bool $getNL( ofstream & ); 44 void $setNL( ofstream &, bool ); 45 bool $getANL( ofstream & ); 46 bool $getPrt( ofstream & ); 47 void $setPrt( ofstream &, bool ); 48 48 49 49 // public … … 56 56 57 57 const char * sepGet( ofstream & ); 58 void sepSet( ofstream &, const char *);58 void sepSet( ofstream &, const char [] ); 59 59 const char * sepGetTuple( ofstream & ); 60 void sepSetTuple( ofstream &, const char *);60 void sepSetTuple( ofstream &, const char [] ); 61 61 62 62 void ends( ofstream & os ); 63 63 int fail( ofstream & ); 64 64 int flush( ofstream & ); 65 void open( ofstream &, const char * name, const char * mode);66 void open( ofstream &, const char * name);65 void open( ofstream &, const char name[], const char mode[] ); 66 void open( ofstream &, const char name[] ); 67 67 void close( ofstream & ); 68 ofstream & write( ofstream &, const char * data, size_t size );69 int fmt( ofstream &, const char format[], ... ) ;68 ofstream & write( ofstream &, const char data[], size_t size ); 69 int fmt( ofstream &, const char format[], ... ) __attribute__(( format(printf, 2, 3) )); 70 70 71 71 void ?{}( ofstream & os ); 72 void ?{}( ofstream & os, const char * name, const char * mode);73 void ?{}( ofstream & os, const char * name);72 void ?{}( ofstream & os, const char name[], const char mode[] ); 73 void ?{}( ofstream & os, const char name[] ); 74 74 void ^?{}( ofstream & os ); 75 75 … … 82 82 83 83 struct ifstream { 84 void * file;85 bool nlOnOff;84 void * $file; 85 bool $nlOnOff; 86 86 }; // ifstream 87 87 … … 92 92 int fail( ifstream & is ); 93 93 int eof( ifstream & is ); 94 void open( ifstream & is, const char * name, const char * mode);95 void open( ifstream & is, const char * name);94 void open( ifstream & is, const char name[], const char mode[] ); 95 void open( ifstream & is, const char name[] ); 96 96 void close( ifstream & is ); 97 97 ifstream & read( ifstream & is, char * data, size_t size ); 98 98 ifstream & ungetc( ifstream & is, char c ); 99 int fmt( ifstream &, const char format[], ... ) ;99 int fmt( ifstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) )); 100 100 101 101 void ?{}( ifstream & is ); 102 void ?{}( ifstream & is, const char * name, const char * mode);103 void ?{}( ifstream & is, const char * name);102 void ?{}( ifstream & is, const char name[], const char mode[] ); 103 void ?{}( ifstream & is, const char name[] ); 104 104 void ^?{}( ifstream & is ); 105 105 -
libcfa/src/gmp.hfa
r8c50aed ra505021 10 10 // Created On : Tue Apr 19 08:43:43 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : S at Jul 13 15:25:05 201913 // Update Count : 2712 // Last Modified On : Sun Feb 9 09:56:54 2020 13 // Update Count : 31 14 14 // 15 15 … … 24 24 25 25 static inline { 26 // constructor 26 // constructor, zero_t/one_t are unnecessary because of relationship with signed/unsigned int 27 27 void ?{}( Int & this ) { mpz_init( this.mpz ); } 28 28 void ?{}( Int & this, Int init ) { mpz_init_set( this.mpz, init.mpz ); } 29 void ?{}( Int & this, zero_t ) { mpz_init_set_si( this.mpz, 0 ); }30 void ?{}( Int & this, one_t ) { mpz_init_set_si( this.mpz, 1 ); }31 29 void ?{}( Int & this, signed long int init ) { mpz_init_set_si( this.mpz, init ); } 32 30 void ?{}( Int & this, unsigned long int init ) { mpz_init_set_ui( this.mpz, init ); } 33 void ?{}( Int & this, const char * val) { if ( mpz_init_set_str( this.mpz, val, 0 ) ) abort(); }31 void ?{}( Int & this, const char val[] ) { if ( mpz_init_set_str( this.mpz, val, 0 ) ) abort(); } 34 32 void ^?{}( Int & this ) { mpz_clear( this.mpz ); } 35 33 … … 37 35 Int ?`mp( signed long int init ) { return (Int){ init }; } 38 36 Int ?`mp( unsigned long int init ) { return (Int){ init }; } 39 Int ?`mp( const char * init) { return (Int){ init }; }37 Int ?`mp( const char init[] ) { return (Int){ init }; } 40 38 41 39 // assignment … … 43 41 Int ?=?( Int & lhs, long int rhs ) { mpz_set_si( lhs.mpz, rhs ); return lhs; } 44 42 Int ?=?( Int & lhs, unsigned long int rhs ) { mpz_set_ui( lhs.mpz, rhs ); return lhs; } 45 Int ?=?( Int & lhs, const char * rhs) { if ( mpz_set_str( lhs.mpz, rhs, 0 ) ) { abort | "invalid string conversion"; } return lhs; }43 Int ?=?( Int & lhs, const char rhs[] ) { if ( mpz_set_str( lhs.mpz, rhs, 0 ) ) { abort | "invalid string conversion"; } return lhs; } 46 44 47 45 char ?=?( char & lhs, Int rhs ) { char val = mpz_get_si( rhs.mpz ); lhs = val; return lhs; } … … 265 263 forall( dtype ostype | ostream( ostype ) ) { 266 264 ostype & ?|?( ostype & os, Int mp ) { 267 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );265 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 268 266 gmp_printf( "%Zd", mp.mpz ); 269 267 sepOn( os ); -
libcfa/src/heap.cfa
r8c50aed ra505021 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 8 21:01:31 201913 // Update Count : 64 712 // Last Modified On : Tue Feb 4 10:04:51 2020 13 // Update Count : 648 14 14 // 15 15 … … 380 380 381 381 382 static inline void checkHeader( bool check, const char * name, void * addr ) {382 static inline void checkHeader( bool check, const char name[], void * addr ) { 383 383 if ( unlikely( check ) ) { // bad address ? 384 384 abort( "Attempt to %s storage %p with address outside the heap.\n" … … 418 418 419 419 420 static inline bool headers( const char * name__attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {420 static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) { 421 421 header = headerAddr( addr ); 422 422 -
libcfa/src/interpose.cfa
r8c50aed ra505021 10 10 // Created On : Wed Mar 29 16:10:31 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jan 30 17:47:32202013 // Update Count : 1 5612 // Last Modified On : Mon Feb 17 10:18:53 2020 13 // Update Count : 166 14 14 // 15 15 … … 29 29 #include "bits/signal.hfa" // sigHandler_? 30 30 #include "startup.hfa" // STARTUP_PRIORITY_CORE 31 #include <assert.h> 31 32 32 33 //============================================================================================= … … 40 41 41 42 typedef void (* generic_fptr_t)(void); 42 generic_fptr_t interpose_symbol( const char * symbol, const char * version) {43 generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) { 43 44 const char * error; 44 45 … … 145 146 extern "C" { 146 147 void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) { 147 abort( false, NULL ); // FIX ME: 0p does not work148 abort( false, "%s", "" ); 148 149 } 149 150 … … 161 162 162 163 void * kernel_abort( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 0p; } 163 void kernel_abort_msg( void * data, char * buffer, int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}164 void kernel_abort_msg( void * data, char buffer[], int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {} 164 165 // See concurrency/kernel.cfa for strong definition used in multi-processor mode. 165 166 int kernel_abort_lastframe( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 4; } … … 169 170 170 171 static void __cfaabi_backtrace( int start ) { 171 enum { 172 Frames = 50, // maximum number of stack frames 173 }; 172 enum { Frames = 50, }; // maximum number of stack frames 174 173 int last = kernel_abort_lastframe(); // skip last N stack frames 175 174 176 175 void * array[Frames]; 177 176 size_t size = backtrace( array, Frames ); 178 char ** messages = backtrace_symbols( array, size ); 177 char ** messages = backtrace_symbols( array, size ); // does not demangle names 179 178 180 179 *index( messages[0], '(' ) = '\0'; // find executable name … … 184 183 char * name = 0p, * offset_begin = 0p, * offset_end = 0p; 185 184 186 for ( char * p = messages[i]; *p; ++p ) {// find parantheses and +offset185 for ( char * p = messages[i]; *p; p += 1 ) { // find parantheses and +offset 187 186 //__cfaabi_bits_print_nolock( "X %s\n", p); 188 187 if ( *p == '(' ) { … … 228 227 __cfaabi_bits_write( STDERR_FILENO, abort_text, len ); 229 228 230 if ( fmt ) { 231 va_list args; 232 va_start( args, fmt ); 233 234 len = vsnprintf( abort_text, abort_text_size, fmt, args ); 235 va_end( args ); 236 __cfaabi_bits_write( STDERR_FILENO, abort_text, len ); 237 238 if ( fmt[strlen( fmt ) - 1] != '\n' ) { // add optional newline if missing at the end of the format text 239 __cfaabi_dbg_write( "\n", 1 ); 240 } 241 } 242 229 assert( fmt ); 230 va_list args; 231 va_start( args, fmt ); 232 233 len = vsnprintf( abort_text, abort_text_size, fmt, args ); 234 va_end( args ); 235 __cfaabi_bits_write( STDERR_FILENO, abort_text, len ); 236 237 if ( fmt[strlen( fmt ) - 1] != '\n' ) { // add optional newline if missing at the end of the format text 238 __cfaabi_dbg_write( "\n", 1 ); 239 } // if 243 240 kernel_abort_msg( kernel_data, abort_text, abort_text_size ); 244 __cfaabi_backtrace( signalAbort ? 4 : 3 ); 241 242 __cfaabi_backtrace( signalAbort ? 4 : 2 ); 245 243 246 244 __cabi_libc.abort(); // print stack trace in handler -
libcfa/src/iostream.cfa
r8c50aed ra505021 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 13 08:07:59 201913 // Update Count : 82 112 // Last Modified On : Thu Feb 20 15:53:23 2020 13 // Update Count : 829 14 14 // 15 15 … … 19 19 #include <stdio.h> 20 20 #include <stdbool.h> // true/false 21 #include <stdint.h> // UINT64_MAX 21 22 //#include <string.h> // strlen, strcmp 22 23 extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); … … 35 36 forall( dtype ostype | ostream( ostype ) ) { 36 37 ostype & ?|?( ostype & os, zero_t ) { 37 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );38 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 38 39 fmt( os, "%d", 0n ); 39 40 return os; … … 44 45 45 46 ostype & ?|?( ostype & os, one_t ) { 46 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );47 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 47 48 fmt( os, "%d", 1n ); 48 49 return os; … … 53 54 54 55 ostype & ?|?( ostype & os, bool b ) { 55 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );56 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 56 57 fmt( os, "%s", b ? "true" : "false" ); 57 58 return os; … … 63 64 ostype & ?|?( ostype & os, char c ) { 64 65 fmt( os, "%c", c ); 65 if ( c == '\n' ) setNL( os, true );66 if ( c == '\n' ) $setNL( os, true ); 66 67 return sepOff( os ); 67 68 } // ?|? … … 71 72 72 73 ostype & ?|?( ostype & os, signed char sc ) { 73 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );74 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 74 75 fmt( os, "%hhd", sc ); 75 76 return os; … … 80 81 81 82 ostype & ?|?( ostype & os, unsigned char usc ) { 82 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );83 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 83 84 fmt( os, "%hhu", usc ); 84 85 return os; … … 89 90 90 91 ostype & ?|?( ostype & os, short int si ) { 91 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );92 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 92 93 fmt( os, "%hd", si ); 93 94 return os; … … 98 99 99 100 ostype & ?|?( ostype & os, unsigned short int usi ) { 100 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );101 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 101 102 fmt( os, "%hu", usi ); 102 103 return os; … … 107 108 108 109 ostype & ?|?( ostype & os, int i ) { 109 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );110 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 110 111 fmt( os, "%d", i ); 111 112 return os; … … 116 117 117 118 ostype & ?|?( ostype & os, unsigned int ui ) { 118 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );119 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 119 120 fmt( os, "%u", ui ); 120 121 return os; … … 125 126 126 127 ostype & ?|?( ostype & os, long int li ) { 127 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );128 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 128 129 fmt( os, "%ld", li ); 129 130 return os; … … 134 135 135 136 ostype & ?|?( ostype & os, unsigned long int uli ) { 136 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );137 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 137 138 fmt( os, "%lu", uli ); 138 139 return os; … … 143 144 144 145 ostype & ?|?( ostype & os, long long int lli ) { 145 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );146 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 146 147 fmt( os, "%lld", lli ); 147 148 return os; … … 152 153 153 154 ostype & ?|?( ostype & os, unsigned long long int ulli ) { 154 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );155 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 155 156 fmt( os, "%llu", ulli ); 156 157 return os; … … 159 160 (ostype &)(os | ulli); ends( os ); 160 161 } // ?|? 162 163 #if defined( __SIZEOF_INT128__ ) 164 // UINT64_MAX 18_446_744_073_709_551_615_ULL 165 #define P10_UINT64 10_000_000_000_000_000_000_ULL // 19 zeroes 166 167 static void base10_128( ostype & os, unsigned int128 val ) { 168 if ( val > UINT64_MAX ) { 169 base10_128( os, val / P10_UINT64 ); // recursive 170 fmt( os, "%.19lu", (uint64_t)(val % P10_UINT64) ); 171 } else { 172 fmt( os, "%lu", (uint64_t)val ); 173 } // if 174 } // base10_128 175 176 static void base10_128( ostype & os, int128 val ) { 177 if ( val < 0 ) { 178 fmt( os, "-" ); // leading negative sign 179 val = -val; 180 } // if 181 base10_128( os, (unsigned int128)val ); // print zero/positive value 182 } // base10_128 183 184 ostype & ?|?( ostype & os, int128 llli ) { 185 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 186 base10_128( os, llli ); 187 return os; 188 } // ?|? 189 void & ?|?( ostype & os, int128 llli ) { 190 (ostype &)(os | llli); ends( os ); 191 } // ?|? 192 193 ostype & ?|?( ostype & os, unsigned int128 ullli ) { 194 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 195 base10_128( os, ullli ); 196 return os; 197 } // ?|? 198 void & ?|?( ostype & os, unsigned int128 ullli ) { 199 (ostype &)(os | ullli); ends( os ); 200 } // ?|? 201 #endif // __SIZEOF_INT128__ 161 202 162 203 #define PrintWithDP( os, format, val, ... ) \ … … 175 216 176 217 ostype & ?|?( ostype & os, float f ) { 177 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );218 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 178 219 PrintWithDP( os, "%g", f ); 179 220 return os; … … 184 225 185 226 ostype & ?|?( ostype & os, double d ) { 186 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );227 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 187 228 PrintWithDP( os, "%.*lg", d, DBL_DIG ); 188 229 return os; … … 193 234 194 235 ostype & ?|?( ostype & os, long double ld ) { 195 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );236 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 196 237 PrintWithDP( os, "%.*Lg", ld, LDBL_DIG ); 197 238 return os; … … 202 243 203 244 ostype & ?|?( ostype & os, float _Complex fc ) { 204 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );245 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 205 246 // os | crealf( fc ) | nonl; 206 247 PrintWithDP( os, "%g", crealf( fc ) ); … … 214 255 215 256 ostype & ?|?( ostype & os, double _Complex dc ) { 216 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );257 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 217 258 // os | creal( dc ) | nonl; 218 259 PrintWithDP( os, "%.*lg", creal( dc ), DBL_DIG ); … … 226 267 227 268 ostype & ?|?( ostype & os, long double _Complex ldc ) { 228 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );269 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 229 270 // os | creall( ldc ) || nonl; 230 271 PrintWithDP( os, "%.*Lg", creall( ldc ), LDBL_DIG ); … … 237 278 } // ?|? 238 279 239 ostype & ?|?( ostype & os, const char * str) {280 ostype & ?|?( ostype & os, const char str[] ) { 240 281 enum { Open = 1, Close, OpenClose }; 241 282 static const unsigned char mask[256] @= { … … 257 298 // first character IS NOT spacing or closing punctuation => add left separator 258 299 unsigned char ch = str[0]; // must make unsigned 259 if ( sepPrt( os ) && mask[ ch ] != Close && mask[ ch ] != OpenClose ) {260 fmt( os, "%s", sepGetCur( os ) );300 if ( $sepPrt( os ) && mask[ ch ] != Close && mask[ ch ] != OpenClose ) { 301 fmt( os, "%s", $sepGetCur( os ) ); 261 302 } // if 262 303 263 304 // if string starts line, must reset to determine open state because separator is off 264 sepReset( os );// reset separator305 $sepReset( os ); // reset separator 265 306 266 307 // last character IS spacing or opening punctuation => turn off separator for next item 267 308 size_t len = strlen( str ); 268 309 ch = str[len - 1]; // must make unsigned 269 if ( sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {310 if ( $sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) { 270 311 sepOn( os ); 271 312 } else { 272 313 sepOff( os ); 273 314 } // if 274 if ( ch == '\n' ) setNL( os, true ); // check *AFTER*sepPrt call above as it resets NL flag315 if ( ch == '\n' ) $setNL( os, true ); // check *AFTER* $sepPrt call above as it resets NL flag 275 316 return write( os, str, len ); 276 317 } // ?|? 277 void ?|?( ostype & os, const char * str ) { 318 319 void ?|?( ostype & os, const char str[] ) { 278 320 (ostype &)(os | str); ends( os ); 279 321 } // ?|? 280 322 281 323 // ostype & ?|?( ostype & os, const char16_t * str ) { 282 // if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );324 // if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 283 325 // fmt( os, "%ls", str ); 284 326 // return os; … … 287 329 // #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous 288 330 // ostype & ?|?( ostype & os, const char32_t * str ) { 289 // if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );331 // if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 290 332 // fmt( os, "%ls", str ); 291 333 // return os; … … 294 336 295 337 // ostype & ?|?( ostype & os, const wchar_t * str ) { 296 // if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );338 // if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 297 339 // fmt( os, "%ls", str ); 298 340 // return os; … … 300 342 301 343 ostype & ?|?( ostype & os, const void * p ) { 302 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );344 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 303 345 fmt( os, "%p", p ); 304 346 return os; … … 315 357 void ?|?( ostype & os, ostype & (* manip)( ostype & ) ) { 316 358 (ostype &)(manip( os )); 317 if ( getPrt( os ) ) ends( os );// something printed ?318 setPrt( os, false ); // turn off359 if ( $getPrt( os ) ) ends( os ); // something printed ? 360 $setPrt( os, false ); // turn off 319 361 } // ?|? 320 362 … … 329 371 ostype & nl( ostype & os ) { 330 372 (ostype &)(os | '\n'); 331 setPrt( os, false ); // turn off332 setNL( os, true );373 $setPrt( os, false ); // turn off 374 $setNL( os, true ); 333 375 flush( os ); 334 376 return sepOff( os ); // prepare for next line … … 336 378 337 379 ostype & nonl( ostype & os ) { 338 setPrt( os, false ); // turn off380 $setPrt( os, false ); // turn off 339 381 return os; 340 382 } // nonl … … 375 417 ostype & ?|?( ostype & os, T arg, Params rest ) { 376 418 (ostype &)(os | arg); // print first argument 377 sepSetCur( os, sepGetTuple( os ) );// switch to tuple separator419 $sepSetCur( os, sepGetTuple( os ) ); // switch to tuple separator 378 420 (ostype &)(os | rest); // print remaining arguments 379 sepSetCur( os, sepGet( os ) ); // switch to regular separator421 $sepSetCur( os, sepGet( os ) ); // switch to regular separator 380 422 return os; 381 423 } // ?|? … … 383 425 // (ostype &)(?|?( os, arg, rest )); ends( os ); 384 426 (ostype &)(os | arg); // print first argument 385 sepSetCur( os, sepGetTuple( os ) );// switch to tuple separator427 $sepSetCur( os, sepGetTuple( os ) ); // switch to tuple separator 386 428 (ostype &)(os | rest); // print remaining arguments 387 sepSetCur( os, sepGet( os ) ); // switch to regular separator429 $sepSetCur( os, sepGet( os ) ); // switch to regular separator 388 430 ends( os ); 389 431 } // ?|? … … 414 456 forall( dtype ostype | ostream( ostype ) ) { \ 415 457 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \ 416 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) ); \458 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \ 417 459 \ 418 460 if ( f.base == 'b' || f.base == 'B' ) { /* bespoke binary format */ \ … … 463 505 \ 464 506 if ( ! f.flags.pc ) { /* no precision */ \ 465 /* printf( "%s\n", &fmtstr[star] ); */ \466 507 fmtstr[sizeof(IFMTNP)-2] = f.base; /* sizeof includes '\0' */ \ 508 /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE ); */ \ 467 509 fmt( os, &fmtstr[star], f.wd, f.val ); \ 468 510 } else { /* precision */ \ 469 511 fmtstr[sizeof(IFMTP)-2] = f.base; /* sizeof includes '\0' */ \ 470 /* printf( "%s \n", &fmtstr[star]); */ \512 /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE ); */ \ 471 513 fmt( os, &fmtstr[star], f.wd, f.pc, f.val ); \ 472 514 } /* if */ \ … … 486 528 IntegralFMTImpl( signed long long int, 'd', "% *ll ", "% *.*ll " ) 487 529 IntegralFMTImpl( unsigned long long int, 'u', "% *ll ", "% *.*ll " ) 530 531 532 #if defined( __SIZEOF_INT128__ ) 533 // Default prefix for non-decimal prints is 0b, 0, 0x. 534 #define IntegralFMTImpl128( T, SIGNED, CODE, IFMTNP, IFMTP ) \ 535 forall( dtype ostype | ostream( ostype ) ) \ 536 static void base10_128( ostype & os, _Ostream_Manip(T) fmt ) { \ 537 if ( fmt.val > UINT64_MAX ) { \ 538 fmt.val /= P10_UINT64; \ 539 base10_128( os, fmt ); /* recursive */ \ 540 _Ostream_Manip(unsigned long long int) fmt2 @= { (uint64_t)(fmt.val % P10_UINT64), 0, 19, 'u', { .all : 0 } }; \ 541 fmt2.flags.nobsdp = true; \ 542 printf( "fmt2 %c %lld %d\n", fmt2.base, fmt2.val, fmt2.all ); \ 543 sepOff( os ); \ 544 (ostype &)(os | fmt2); \ 545 } else { \ 546 printf( "fmt %c %lld %d\n", fmt.base, fmt.val, fmt.all ); \ 547 (ostype &)(os | fmt); \ 548 } /* if */ \ 549 } /* base10_128 */ \ 550 forall( dtype ostype | ostream( ostype ) ) { \ 551 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \ 552 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \ 553 \ 554 if ( f.base == 'b' | f.base == 'o' | f.base == 'x' | f.base == 'X' ) { \ 555 unsigned long long int msig = (unsigned long long int)(f.val >> 64); \ 556 unsigned long long int lsig = (unsigned long long int)(f.val); \ 557 _Ostream_Manip(SIGNED long long int) fmt @= { msig, f.wd, f.pc, f.base, { .all : f.all } }; \ 558 _Ostream_Manip(unsigned long long int) fmt2 @= { lsig, 0, 0, f.base, { .all : 0 } }; \ 559 if ( msig == 0 ) { \ 560 fmt.val = lsig; \ 561 (ostype &)(os | fmt); \ 562 } else { \ 563 fmt2.flags.pad0 = fmt2.flags.nobsdp = true; \ 564 if ( f.base == 'b' ) { \ 565 if ( f.wd > 64 ) fmt.wd = f.wd - 64; \ 566 fmt2.wd = 64; \ 567 (ostype &)(os | fmt | "" | fmt2); \ 568 } else if ( f.base == 'o' ) { \ 569 fmt.val = (unsigned long long int)fmt.val >> 2; \ 570 if ( f.wd > 21 ) fmt.wd = f.wd - 21; \ 571 fmt2.wd = 1; \ 572 fmt2.val = ((msig & 0x3) << 1) + 1; \ 573 (ostype &)(os | fmt | "" | fmt2); \ 574 sepOff( os ); \ 575 fmt2.wd = 21; \ 576 fmt2.val = lsig & 0x7fffffffffffffff; \ 577 (ostype &)(os | fmt2); \ 578 } else { \ 579 if ( f.flags.left ) { \ 580 if ( f.wd > 16 ) fmt2.wd = f.wd - 16; \ 581 fmt.wd = 16; \ 582 } else { \ 583 if ( f.wd > 16 ) fmt.wd = f.wd - 16; \ 584 fmt2.wd = 16; \ 585 } /* if */ \ 586 (ostype &)(os | fmt | "" | fmt2); \ 587 } /* if */ \ 588 } /* if */ \ 589 } else { \ 590 base10_128( os, f ); \ 591 } /* if */ \ 592 return os; \ 593 } /* ?|? */ \ 594 void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \ 595 } // distribution 596 597 IntegralFMTImpl128( int128, signed, 'd', "% *ll ", "% *.*ll " ) 598 IntegralFMTImpl128( unsigned int128, unsigned, 'u', "% *ll ", "% *.*ll " ) 599 #endif // __SIZEOF_INT128__ 488 600 489 601 //*********************************** floating point *********************************** … … 513 625 forall( dtype ostype | ostream( ostype ) ) { \ 514 626 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \ 515 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) ); \627 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \ 516 628 char fmtstr[sizeof(DFMTP)]; /* sizeof includes '\0' */ \ 517 629 if ( ! f.flags.pc ) memcpy( &fmtstr, DFMTNP, sizeof(DFMTNP) ); \ … … 536 648 return os; \ 537 649 } /* ?|? */ \ 650 \ 538 651 void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \ 539 652 } // distribution … … 555 668 } // if 556 669 557 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );670 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 558 671 559 672 #define CFMTNP "% * " … … 571 684 return os; 572 685 } // ?|? 686 573 687 void ?|?( ostype & os, _Ostream_Manip(char) f ) { (ostype &)(os | f); ends( os ); } 574 688 } // distribution … … 592 706 } // if 593 707 594 if ( sepPrt( os ) ) fmt( os, "%s",sepGetCur( os ) );708 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); 595 709 596 710 #define SFMTNP "% * " … … 616 730 return os; 617 731 } // ?|? 732 618 733 void ?|?( ostype & os, _Ostream_Manip(const char *) f ) { (ostype &)(os | f); ends( os ); } 619 734 } // distribution … … 735 850 } // ?|? 736 851 737 // istype & ?|?( istype & is, const char * fmt) {852 // istype & ?|?( istype & is, const char fmt[] ) { 738 853 // fmt( is, fmt, "" ); 739 854 // return is; -
libcfa/src/iostream.hfa
r8c50aed ra505021 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 12 12:08:38 201913 // Update Count : 33 412 // Last Modified On : Thu Feb 20 15:30:56 2020 13 // Update Count : 337 14 14 // 15 15 … … 24 24 trait ostream( dtype ostype ) { 25 25 // private 26 bool sepPrt( ostype & ); // get separator state (on/off)27 void sepReset( ostype & ); // set separator state to default state28 void sepReset( ostype &, bool ); // set separator and default state29 const char * sepGetCur( ostype & );// get current separator string30 void sepSetCur( ostype &, const char *); // set current separator string31 bool getNL( ostype & );// check newline32 void setNL( ostype &, bool ); // saw newline33 bool getANL( ostype & ); // get auto newline (on/off)34 bool getPrt( ostype & ); // get fmt called in output cascade35 void setPrt( ostype &, bool ); // set fmt called in output cascade26 bool $sepPrt( ostype & ); // get separator state (on/off) 27 void $sepReset( ostype & ); // set separator state to default state 28 void $sepReset( ostype &, bool ); // set separator and default state 29 const char * $sepGetCur( ostype & ); // get current separator string 30 void $sepSetCur( ostype &, const char [] ); // set current separator string 31 bool $getNL( ostype & ); // check newline 32 void $setNL( ostype &, bool ); // saw newline 33 bool $getANL( ostype & ); // get auto newline (on/off) 34 bool $getPrt( ostype & ); // get fmt called in output cascade 35 void $setPrt( ostype &, bool ); // set fmt called in output cascade 36 36 // public 37 37 void sepOn( ostype & ); // turn separator state on … … 43 43 44 44 const char * sepGet( ostype & ); // get separator string 45 void sepSet( ostype &, const char *); // set separator to string (15 character maximum)45 void sepSet( ostype &, const char [] ); // set separator to string (15 character maximum) 46 46 const char * sepGetTuple( ostype & ); // get tuple separator string 47 void sepSetTuple( ostype &, const char * );// set tuple separator to string (15 character maximum)47 void sepSetTuple( ostype &, const char [] ); // set tuple separator to string (15 character maximum) 48 48 49 49 void ends( ostype & os ); // end of output statement 50 50 int fail( ostype & ); 51 51 int flush( ostype & ); 52 void open( ostype & os, const char * name, const char * mode);52 void open( ostype & os, const char name[], const char mode[] ); 53 53 void close( ostype & os ); 54 ostype & write( ostype &, const char *, size_t );54 ostype & write( ostype &, const char [], size_t ); 55 55 int fmt( ostype &, const char format[], ... ) __attribute__(( format(printf, 2, 3) )); 56 56 }; // ostream … … 98 98 ostype & ?|?( ostype &, unsigned long long int ); 99 99 void ?|?( ostype &, unsigned long long int ); 100 #if defined( __SIZEOF_INT128__ ) 101 ostype & ?|?( ostype &, int128 ); 102 void ?|?( ostype &, int128 ); 103 ostype & ?|?( ostype &, unsigned int128 ); 104 void ?|?( ostype &, unsigned int128 ); 105 #endif // __SIZEOF_INT128__ 100 106 101 107 ostype & ?|?( ostype &, float ); … … 113 119 void ?|?( ostype &, long double _Complex ); 114 120 115 ostype & ?|?( ostype &, const char *);116 void ?|?( ostype &, const char *);121 ostype & ?|?( ostype &, const char [] ); 122 void ?|?( ostype &, const char [] ); 117 123 // ostype & ?|?( ostype &, const char16_t * ); 118 124 #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous … … 206 212 IntegralFMTDecl( signed long long int, 'd' ) 207 213 IntegralFMTDecl( unsigned long long int, 'u' ) 214 #if defined( __SIZEOF_INT128__ ) 215 IntegralFMTDecl( int128, 'd' ) 216 IntegralFMTDecl( unsigned int128, 'u' ) 217 #endif 208 218 209 219 //*********************************** floating point *********************************** … … 256 266 257 267 static inline { 258 _Ostream_Manip(const char *) bin( const char * s) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'b', { .all : 0 } }; }259 _Ostream_Manip(const char *) oct( const char * s) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'o', { .all : 0 } }; }260 _Ostream_Manip(const char *) hex( const char * s) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'x', { .all : 0 } }; }261 _Ostream_Manip(const char *) wd( unsigned int w, const char * s) { return (_Ostream_Manip(const char *))@{ s, w, 0, 's', { .all : 0 } }; }262 _Ostream_Manip(const char *) wd( unsigned int w, unsigned char pc, const char * s) { return (_Ostream_Manip(const char *))@{ s, w, pc, 's', { .flags.pc : true } }; }268 _Ostream_Manip(const char *) bin( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'b', { .all : 0 } }; } 269 _Ostream_Manip(const char *) oct( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'o', { .all : 0 } }; } 270 _Ostream_Manip(const char *) hex( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'x', { .all : 0 } }; } 271 _Ostream_Manip(const char *) wd( unsigned int w, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, w, 0, 's', { .all : 0 } }; } 272 _Ostream_Manip(const char *) wd( unsigned int w, unsigned char pc, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, w, pc, 's', { .flags.pc : true } }; } 263 273 _Ostream_Manip(const char *) & wd( unsigned int w, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; } 264 274 _Ostream_Manip(const char *) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } … … 281 291 int fail( istype & ); 282 292 int eof( istype & ); 283 void open( istype & is, const char * name);293 void open( istype & is, const char name[] ); 284 294 void close( istype & is ); 285 295 istype & read( istype &, char *, size_t ); … … 316 326 istype & ?|?( istype &, long double _Complex & ); 317 327 318 // istype & ?|?( istype &, const char *);328 // istype & ?|?( istype &, const char [] ); 319 329 istype & ?|?( istype &, char * ); 320 330 … … 343 353 static inline { 344 354 _Istream_Cstr skip( unsigned int n ) { return (_Istream_Cstr){ 0p, 0p, n, { .all : 0 } }; } 345 _Istream_Cstr skip( const char * scanset) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; }346 _Istream_Cstr incl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; }347 _Istream_Cstr & incl( const char * scanset, _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }348 _Istream_Cstr excl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }349 _Istream_Cstr & excl( const char * scanset, _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }350 _Istream_Cstr ignore( const char * s) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }355 _Istream_Cstr skip( const char scanset[] ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; } 356 _Istream_Cstr incl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; } 357 _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; } 358 _Istream_Cstr excl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; } 359 _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; } 360 _Istream_Cstr ignore( const char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; } 351 361 _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; } 352 _Istream_Cstr wdi( unsigned int w, char * s) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }362 _Istream_Cstr wdi( unsigned int w, char s[] ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; } 353 363 _Istream_Cstr & wdi( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; } 354 364 } // distribution -
libcfa/src/math.hfa
r8c50aed ra505021 10 10 // Created On : Mon Apr 18 23:37:04 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 13 11:02:15 201813 // Update Count : 11 612 // Last Modified On : Tue Feb 4 10:27:11 2020 13 // Update Count : 117 14 14 // 15 15 … … 51 51 static inline long double fdim( long double x, long double y ) { return fdiml( x, y ); } 52 52 53 static inline float nan( const char * tag) { return nanf( tag ); }54 // extern "C" { double nan( const char *); }55 static inline long double nan( const char * tag) { return nanl( tag ); }53 static inline float nan( const char tag[] ) { return nanf( tag ); } 54 // extern "C" { double nan( const char [] ); } 55 static inline long double nan( const char tag[] ) { return nanl( tag ); } 56 56 57 57 //---------------------- Exponential ---------------------- -
libcfa/src/rational.cfa
r8c50aed ra505021 10 10 // Created On : Wed Apr 6 17:54:28 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 12 18:12:08 201913 // Update Count : 18 412 // Last Modified On : Sat Feb 8 17:56:36 2020 13 // Update Count : 187 14 14 // 15 15 … … 56 56 } // rational 57 57 58 void ?{}( Rational(RationalImpl) & r, zero_t ) { 59 r{ (RationalImpl){0}, (RationalImpl){1} }; 60 } // rational 61 62 void ?{}( Rational(RationalImpl) & r, one_t ) { 63 r{ (RationalImpl){1}, (RationalImpl){1} }; 64 } // rational 58 65 59 66 // getter for numerator/denominator -
libcfa/src/startup.cfa
r8c50aed ra505021 10 10 // Created On : Tue Jul 24 16:21:57 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 13 13:16:45 201913 // Update Count : 2912 // Last Modified On : Tue Feb 4 13:03:18 2020 13 // Update Count : 30 14 14 // 15 15 … … 41 41 struct __spinlock_t; 42 42 extern "C" { 43 void __cfaabi_dbg_record(struct __spinlock_t & this, const char * prev_name) __attribute__(( weak )) {}43 void __cfaabi_dbg_record(struct __spinlock_t & this, const char prev_name[]) __attribute__(( weak )) {} 44 44 } 45 45 -
libcfa/src/stdhdr/assert.h
r8c50aed ra505021 10 10 // Created On : Mon Jul 4 23:25:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jul 31 23:09:32 201713 // Update Count : 1 312 // Last Modified On : Tue Feb 4 12:58:49 2020 13 // Update Count : 15 14 14 // 15 15 … … 27 27 #define assertf( expr, fmt, ... ) ((expr) ? ((void)0) : __assert_fail_f(__VSTRINGIFY__(expr), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, ## __VA_ARGS__ )) 28 28 29 void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) __attribute__((noreturn, format( printf, 5, 6) ));29 void __assert_fail_f( const char assertion[], const char file[], unsigned int line, const char function[], const char fmt[], ... ) __attribute__((noreturn, format( printf, 5, 6) )); 30 30 #endif 31 31 -
libcfa/src/stdhdr/bfdlink.h
r8c50aed ra505021 10 10 // Created On : Tue Jul 18 07:26:04 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 1 07:15:29202013 // Update Count : 512 // Last Modified On : Fri Feb 7 19:05:08 2020 13 // Update Count : 6 14 14 // 15 15 16 16 // include file uses the CFA keyword "with". 17 17 #if ! defined( with ) // nesting ? 18 #define with ``with ``// make keyword an identifier18 #define with ``with // make keyword an identifier 19 19 #define __CFA_BFDLINK_H__ 20 20 #endif -
libcfa/src/stdhdr/hwloc.h
r8c50aed ra505021 10 10 // Created On : Tue Jul 18 07:45:00 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 1 07:15:39202013 // Update Count : 512 // Last Modified On : Fri Feb 7 19:05:18 2020 13 // Update Count : 6 14 14 // 15 15 16 16 // include file uses the CFA keyword "thread". 17 17 #if ! defined( thread ) // nesting ? 18 #define thread ``thread ``// make keyword an identifier18 #define thread ``thread // make keyword an identifier 19 19 #define __CFA_HWLOC_H__ 20 20 #endif -
libcfa/src/stdhdr/krb5.h
r8c50aed ra505021 10 10 // Created On : Tue Jul 18 07:55:44 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 1 07:15:47202013 // Update Count : 512 // Last Modified On : Fri Feb 7 19:05:35 2020 13 // Update Count : 6 14 14 // 15 15 16 16 // include file uses the CFA keyword "enable". 17 17 #if ! defined( enable ) // nesting ? 18 #define enable ``enable ``// make keyword an identifier18 #define enable ``enable // make keyword an identifier 19 19 #define __CFA_KRB5_H__ 20 20 #endif -
libcfa/src/stdhdr/math.h
r8c50aed ra505021 10 10 // Created On : Mon Jul 4 23:25:26 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 1 07:15:58202013 // Update Count : 1 412 // Last Modified On : Fri Feb 7 19:05:27 2020 13 // Update Count : 15 14 14 // 15 15 16 16 extern "C" { 17 17 #if ! defined( exception ) // nesting ? 18 #define exception ``exception ``// make keyword an identifier18 #define exception ``exception // make keyword an identifier 19 19 #define __CFA_MATH_H__ 20 20 #endif -
libcfa/src/stdhdr/sys/ucontext.h
r8c50aed ra505021 10 10 // Created On : Thu Feb 8 23:48:16 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 1 07:16:05202013 // Update Count : 512 // Last Modified On : Fri Feb 7 19:05:41 2020 13 // Update Count : 6 14 14 // 15 15 16 16 #if ! defined( ftype ) // nesting ? 17 #define ftype ``ftype ``// make keyword an identifier17 #define ftype ``ftype // make keyword an identifier 18 18 #define __CFA_UCONTEXT_H__ 19 19 #endif -
libcfa/src/stdlib.cfa
r8c50aed ra505021 10 10 // Created On : Thu Jan 28 17:10:29 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Nov 20 17:22:47 201913 // Update Count : 48 512 // Last Modified On : Tue Feb 4 08:27:08 2020 13 // Update Count : 486 14 14 // 15 15 … … 107 107 //--------------------------------------- 108 108 109 float _Complex strto( const char * sptr, char ** eptr ) {109 float _Complex strto( const char sptr[], char ** eptr ) { 110 110 float re, im; 111 111 char * eeptr; … … 118 118 } // strto 119 119 120 double _Complex strto( const char * sptr, char ** eptr ) {120 double _Complex strto( const char sptr[], char ** eptr ) { 121 121 double re, im; 122 122 char * eeptr; … … 129 129 } // strto 130 130 131 long double _Complex strto( const char * sptr, char ** eptr ) {131 long double _Complex strto( const char sptr[], char ** eptr ) { 132 132 long double re, im; 133 133 char * eeptr; -
libcfa/src/stdlib.hfa
r8c50aed ra505021 10 10 // Created On : Thu Jan 28 17:12:35 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Nov 29 23:08:02 201913 // Update Count : 40 012 // Last Modified On : Tue Feb 4 08:27:01 2020 13 // Update Count : 401 14 14 // 15 15 … … 193 193 194 194 static inline { 195 int strto( const char * sptr, char ** eptr, int base ) { return (int)strtol( sptr, eptr, base ); }196 unsigned int strto( const char * sptr, char ** eptr, int base ) { return (unsigned int)strtoul( sptr, eptr, base ); }197 long int strto( const char * sptr, char ** eptr, int base ) { return strtol( sptr, eptr, base ); }198 unsigned long int strto( const char * sptr, char ** eptr, int base ) { return strtoul( sptr, eptr, base ); }199 long long int strto( const char * sptr, char ** eptr, int base ) { return strtoll( sptr, eptr, base ); }200 unsigned long long int strto( const char * sptr, char ** eptr, int base ) { return strtoull( sptr, eptr, base ); }201 202 float strto( const char * sptr, char ** eptr ) { return strtof( sptr, eptr ); }203 double strto( const char * sptr, char ** eptr ) { return strtod( sptr, eptr ); }204 long double strto( const char * sptr, char ** eptr ) { return strtold( sptr, eptr ); }205 } // distribution 206 207 float _Complex strto( const char * sptr, char ** eptr );208 double _Complex strto( const char * sptr, char ** eptr );209 long double _Complex strto( const char * sptr, char ** eptr );195 int strto( const char sptr[], char ** eptr, int base ) { return (int)strtol( sptr, eptr, base ); } 196 unsigned int strto( const char sptr[], char ** eptr, int base ) { return (unsigned int)strtoul( sptr, eptr, base ); } 197 long int strto( const char sptr[], char ** eptr, int base ) { return strtol( sptr, eptr, base ); } 198 unsigned long int strto( const char sptr[], char ** eptr, int base ) { return strtoul( sptr, eptr, base ); } 199 long long int strto( const char sptr[], char ** eptr, int base ) { return strtoll( sptr, eptr, base ); } 200 unsigned long long int strto( const char sptr[], char ** eptr, int base ) { return strtoull( sptr, eptr, base ); } 201 202 float strto( const char sptr[], char ** eptr ) { return strtof( sptr, eptr ); } 203 double strto( const char sptr[], char ** eptr ) { return strtod( sptr, eptr ); } 204 long double strto( const char sptr[], char ** eptr ) { return strtold( sptr, eptr ); } 205 } // distribution 206 207 float _Complex strto( const char sptr[], char ** eptr ); 208 double _Complex strto( const char sptr[], char ** eptr ); 209 long double _Complex strto( const char sptr[], char ** eptr ); 210 210 211 211 static inline { 212 int ato( const char * sptr) { return (int)strtol( sptr, 0p, 10 ); }213 unsigned int ato( const char * sptr) { return (unsigned int)strtoul( sptr, 0p, 10 ); }214 long int ato( const char * sptr) { return strtol( sptr, 0p, 10 ); }215 unsigned long int ato( const char * sptr) { return strtoul( sptr, 0p, 10 ); }216 long long int ato( const char * sptr) { return strtoll( sptr, 0p, 10 ); }217 unsigned long long int ato( const char * sptr) { return strtoull( sptr, 0p, 10 ); }218 219 float ato( const char * sptr) { return strtof( sptr, 0p ); }220 double ato( const char * sptr) { return strtod( sptr, 0p ); }221 long double ato( const char * sptr) { return strtold( sptr, 0p ); }222 223 float _Complex ato( const char * sptr) { return strto( sptr, 0p ); }224 double _Complex ato( const char * sptr) { return strto( sptr, 0p ); }225 long double _Complex ato( const char * sptr) { return strto( sptr, 0p ); }212 int ato( const char sptr[] ) { return (int)strtol( sptr, 0p, 10 ); } 213 unsigned int ato( const char sptr[] ) { return (unsigned int)strtoul( sptr, 0p, 10 ); } 214 long int ato( const char sptr[] ) { return strtol( sptr, 0p, 10 ); } 215 unsigned long int ato( const char sptr[] ) { return strtoul( sptr, 0p, 10 ); } 216 long long int ato( const char sptr[] ) { return strtoll( sptr, 0p, 10 ); } 217 unsigned long long int ato( const char sptr[] ) { return strtoull( sptr, 0p, 10 ); } 218 219 float ato( const char sptr[] ) { return strtof( sptr, 0p ); } 220 double ato( const char sptr[] ) { return strtod( sptr, 0p ); } 221 long double ato( const char sptr[] ) { return strtold( sptr, 0p ); } 222 223 float _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); } 224 double _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); } 225 long double _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); } 226 226 } // distribution 227 227 -
libcfa/src/time.cfa
r8c50aed ra505021 10 10 // Created On : Tue Mar 27 13:33:14 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Jan 5 17:27:40202013 // Update Count : 6912 // Last Modified On : Tue Feb 4 08:24:18 2020 13 // Update Count : 70 14 14 // 15 15 … … 129 129 } // dd_mm_yy 130 130 131 size_t strftime( char * buf, size_t size, const char * fmt, Time time ) with( time ) {131 size_t strftime( char buf[], size_t size, const char fmt[], Time time ) with( time ) { 132 132 time_t s = tn / TIMEGRAN; 133 133 tm tm; -
libcfa/src/time.hfa
r8c50aed ra505021 10 10 // Created On : Wed Mar 14 23:18:57 2018 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Jan 6 12:50:16202013 // Update Count : 65 312 // Last Modified On : Tue Feb 4 08:24:32 2020 13 // Update Count : 654 14 14 // 15 15 … … 191 191 } // dmy 192 192 193 size_t strftime( char * buf, size_t size, const char * fmt, Time time );193 size_t strftime( char buf[], size_t size, const char fmt[], Time time ); 194 194 195 195 //------------------------- timeval (cont) ------------------------- -
longrun_tests/Makefile.in
r8c50aed ra505021 502 502 am__v_GOC_0 = @echo " GOC " $@; 503 503 am__v_GOC_1 = 504 AM_V_PY = $(am__v_PY_@AM_V@) 505 am__v_PY_ = $(am__v_PY_@AM_DEFAULT_V@) 506 am__v_PY_0 = @echo " PYTHON " $@; 507 am__v_PY_1 = 504 508 AM_V_RUST = $(am__v_RUST_@AM_V@) 505 509 am__v_RUST_ = $(am__v_RUST_@AM_DEFAULT_V@) 506 am__v_RUST_0 = @echo " RUST 510 am__v_RUST_0 = @echo " RUST " $@; 507 511 am__v_RUST_1 = 508 512 AM_V_NODEJS = $(am__v_NODEJS_@AM_V@) 509 513 am__v_NODEJS_ = $(am__v_NODEJS_@AM_DEFAULT_V@) 510 am__v_NODEJS_0 = @echo " NODEJS 514 am__v_NODEJS_0 = @echo " NODEJS " $@; 511 515 am__v_NODEJS_1 = 512 516 AM_V_JAVAC = $(am__v_JAVAC_@AM_V@) -
src/CodeGen/CodeGenerator.cc
r8c50aed ra505021 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 13 23:13:28 201913 // Update Count : 5 0812 // Last Modified On : Sun Feb 16 08:32:48 2020 13 // Update Count : 532 14 14 // 15 15 #include "CodeGenerator.h" … … 39 39 int CodeGenerator::tabsize = 4; 40 40 41 // the kinds of statements that would ideally be followed by whitespace41 // The kinds of statements that would ideally be followed by whitespace. 42 42 bool wantSpacing( Statement * stmt) { 43 43 return dynamic_cast< IfStmt * >( stmt ) || dynamic_cast< CompoundStmt * >( stmt ) || … … 78 78 } 79 79 80 /* Using updateLocation at the beginning of a node and endl 81 * within a node should become the method of formating. 82 */ 80 // Using updateLocation at the beginning of a node and endl within a node should become the method of formating. 83 81 void CodeGenerator::updateLocation( CodeLocation const & to ) { 84 82 // skip if linemarks shouldn't appear or if codelocation is unset … … 95 93 } else { 96 94 output << "\n# " << to.first_line << " \"" << to.filename 97 95 << "\"\n" << indent; 98 96 currentLocation = to; 99 97 } … … 131 129 132 130 void CodeGenerator::genAttributes( list< Attribute * > & attributes ) { 133 131 if ( attributes.empty() ) return; 134 132 output << "__attribute__ (("; 135 133 for ( list< Attribute * >::iterator attr( attributes.begin() );; ) { … … 140 138 output << ")"; 141 139 } // if 142 140 if ( ++attr == attributes.end() ) break; 143 141 output << ","; // separator 144 142 } // for … … 165 163 previsit( (BaseSyntaxNode *)node ); 166 164 GuardAction( [this, node](){ 167 if ( options.printExprTypes && node->result ) {168 output << " /* " << genType( node->result, "", options ) << " */ ";169 }170 } );165 if ( options.printExprTypes && node->result ) { 166 output << " /* " << genType( node->result, "", options ) << " */ "; 167 } 168 } ); 171 169 } 172 170 … … 399 397 extension( applicationExpr ); 400 398 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr* >( applicationExpr->get_function() ) ) { 401 OperatorInfoopInfo;402 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo) ) {399 const OperatorInfo * opInfo; 400 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && ( opInfo = operatorLookup( varExpr->get_var()->get_name() ) ) ) { 403 401 std::list< Expression* >::iterator arg = applicationExpr->get_args().begin(); 404 switch ( opInfo .type ) {402 switch ( opInfo->type ) { 405 403 case OT_INDEX: 406 404 assert( applicationExpr->get_args().size() == 2 ); … … 423 421 output << "("; 424 422 (*arg++)->accept( *visitor ); 425 output << ") /* " << opInfo .inputName << " */";423 output << ") /* " << opInfo->inputName << " */"; 426 424 } else if ( applicationExpr->get_args().size() == 2 ) { 427 425 // intrinsic two parameter constructors are essentially bitwise assignment 428 426 output << "("; 429 427 (*arg++)->accept( *visitor ); 430 output << opInfo .symbol;428 output << opInfo->symbol; 431 429 (*arg)->accept( *visitor ); 432 output << ") /* " << opInfo .inputName << " */";430 output << ") /* " << opInfo->inputName << " */"; 433 431 } else { 434 432 // no constructors with 0 or more than 2 parameters … … 441 439 assert( applicationExpr->get_args().size() == 1 ); 442 440 output << "("; 443 output << opInfo .symbol;441 output << opInfo->symbol; 444 442 (*arg)->accept( *visitor ); 445 443 output << ")"; … … 450 448 assert( applicationExpr->get_args().size() == 1 ); 451 449 (*arg)->accept( *visitor ); 452 output << opInfo .symbol;450 output << opInfo->symbol; 453 451 break; 454 452 … … 459 457 output << "("; 460 458 (*arg++)->accept( *visitor ); 461 output << opInfo .symbol;459 output << opInfo->symbol; 462 460 (*arg)->accept( *visitor ); 463 461 output << ")"; … … 486 484 extension( untypedExpr ); 487 485 if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->function ) ) { 488 OperatorInfo opInfo;489 if ( op eratorLookup( nameExpr->name, opInfo )) {486 const OperatorInfo * opInfo = operatorLookup( nameExpr->name ); 487 if ( opInfo ) { 490 488 std::list< Expression* >::iterator arg = untypedExpr->args.begin(); 491 switch ( opInfo .type ) {489 switch ( opInfo->type ) { 492 490 case OT_INDEX: 493 491 assert( untypedExpr->args.size() == 2 ); … … 508 506 output << "("; 509 507 (*arg++)->accept( *visitor ); 510 output << ") /* " << opInfo .inputName << " */";508 output << ") /* " << opInfo->inputName << " */"; 511 509 } else if ( untypedExpr->get_args().size() == 2 ) { 512 510 // intrinsic two parameter constructors are essentially bitwise assignment 513 511 output << "("; 514 512 (*arg++)->accept( *visitor ); 515 output << opInfo .symbol;513 output << opInfo->symbol; 516 514 (*arg)->accept( *visitor ); 517 output << ") /* " << opInfo .inputName << " */";515 output << ") /* " << opInfo->inputName << " */"; 518 516 } else { 519 517 // no constructors with 0 or more than 2 parameters … … 521 519 output << "("; 522 520 (*arg++)->accept( *visitor ); 523 output << opInfo .symbol << "{ ";521 output << opInfo->symbol << "{ "; 524 522 genCommaList( arg, untypedExpr->args.end() ); 525 output << "}) /* " << opInfo .inputName << " */";523 output << "}) /* " << opInfo->inputName << " */"; 526 524 } // if 527 525 break; … … 532 530 assert( untypedExpr->args.size() == 1 ); 533 531 output << "("; 534 output << opInfo .symbol;532 output << opInfo->symbol; 535 533 (*arg)->accept( *visitor ); 536 534 output << ")"; … … 541 539 assert( untypedExpr->args.size() == 1 ); 542 540 (*arg)->accept( *visitor ); 543 output << opInfo .symbol;541 output << opInfo->symbol; 544 542 break; 545 543 … … 549 547 output << "("; 550 548 (*arg++)->accept( *visitor ); 551 output << opInfo .symbol;549 output << opInfo->symbol; 552 550 (*arg)->accept( *visitor ); 553 551 output << ")"; … … 581 579 void CodeGenerator::postvisit( NameExpr * nameExpr ) { 582 580 extension( nameExpr ); 583 OperatorInfo opInfo;584 if ( op eratorLookup( nameExpr->name, opInfo )) {585 if ( opInfo .type == OT_CONSTANT ) {586 output << opInfo .symbol;581 const OperatorInfo * opInfo = operatorLookup( nameExpr->name ); 582 if ( opInfo ) { 583 if ( opInfo->type == OT_CONSTANT ) { 584 output << opInfo->symbol; 587 585 } else { 588 output << opInfo .outputName;586 output << opInfo->outputName; 589 587 } 590 588 } else { … … 654 652 void CodeGenerator::postvisit( VariableExpr * variableExpr ) { 655 653 extension( variableExpr ); 656 OperatorInfoopInfo;657 if ( variableExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( variableExpr->get_var()->get_name(), opInfo ) && opInfo.type == OT_CONSTANT ) {658 output << opInfo .symbol;654 const OperatorInfo * opInfo; 655 if ( variableExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && (opInfo = operatorLookup( variableExpr->get_var()->get_name() )) && opInfo->type == OT_CONSTANT ) { 656 output << opInfo->symbol; 659 657 } else { 660 658 output << mangleName( variableExpr->get_var() ); … … 1011 1009 case BranchStmt::FallThroughDefault: 1012 1010 assertf( ! options.genC, "fallthru should not reach code generation." ); 1013 1011 output << "fallthru"; 1014 1012 break; 1015 1013 } // switch … … 1035 1033 1036 1034 output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ? 1037 1035 "throw" : "throwResume"); 1038 1036 if (throwStmt->get_expr()) { 1039 1037 output << " "; … … 1050 1048 1051 1049 output << ((stmt->get_kind() == CatchStmt::Terminate) ? 1052 "catch" : "catchResume");1050 "catch" : "catchResume"); 1053 1051 output << "( "; 1054 1052 stmt->decl->accept( *visitor ); … … 1187 1185 1188 1186 std::string genName( DeclarationWithType * decl ) { 1189 CodeGen::OperatorInfo opInfo;1190 if ( op eratorLookup( decl->get_name(), opInfo )) {1191 return opInfo .outputName;1187 const OperatorInfo * opInfo = operatorLookup( decl->get_name() ); 1188 if ( opInfo ) { 1189 return opInfo->outputName; 1192 1190 } else { 1193 1191 return decl->get_name(); -
src/CodeGen/CodeGenerator.h
r8c50aed ra505021 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Apr 30 12:01:00 201913 // Update Count : 5711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Feb 16 03:58:31 2020 13 // Update Count : 62 14 14 // 15 15 … … 29 29 namespace CodeGen { 30 30 struct CodeGenerator : public WithShortCircuiting, public WithGuards, public WithVisitorRef<CodeGenerator> { 31 31 static int tabsize; 32 32 33 33 CodeGenerator( std::ostream &os, bool pretty = false, bool genC = false, bool lineMarks = false, bool printExprTypes = false ); … … 104 104 void postvisit( AsmStmt * ); 105 105 void postvisit( DirectiveStmt * ); 106 void postvisit( AsmDecl * ); // special: statement in declaration context106 void postvisit( AsmDecl * ); // special: statement in declaration context 107 107 void postvisit( IfStmt * ); 108 108 void postvisit( SwitchStmt * ); … … 147 147 LabelPrinter printLabels; 148 148 Options options; 149 public:149 public: 150 150 LineEnder endl; 151 private:151 private: 152 152 153 153 CodeLocation currentLocation; … … 162 162 template< class Iterator > 163 163 void CodeGenerator::genCommaList( Iterator begin, Iterator end ) { 164 164 if ( begin == end ) return; 165 165 for ( ;; ) { 166 166 (*begin++)->accept( *visitor ); 167 167 if ( begin == end ) break; 168 168 output << ", "; // separator 169 169 } // for -
src/CodeGen/FixMain.h
r8c50aed ra505021 10 10 // Created On : Thr Jan 12 14:11:09 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 13 23:12:21 201913 // Update Count : 312 // Last Modified On : Sun Feb 16 03:24:32 2020 13 // Update Count : 5 14 14 // 15 15 … … 42 42 static std::unique_ptr<FunctionDecl> main_signature; 43 43 }; 44 } ;44 } // namespace CodeGen -
src/CodeGen/GenType.h
r8c50aed ra505021 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tue Apr 30 11:47:00 201913 // Update Count : 311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Feb 16 04:11:40 2020 13 // Update Count : 5 14 14 // 15 15 … … 25 25 std::string genType( Type *type, const std::string &baseString, const Options &options ); 26 26 std::string genType( Type *type, const std::string &baseString, bool pretty = false, bool genC = false, bool lineMarks = false ); 27 27 std::string genPrettyType( Type * type, const std::string & baseString ); 28 28 } // namespace CodeGen 29 29 -
src/CodeGen/Generate.cc
r8c50aed ra505021 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Dec 13 23:38:56 201913 // Update Count : 812 // Last Modified On : Sun Feb 16 03:01:51 2020 13 // Update Count : 9 14 14 // 15 15 #include "Generate.h" … … 64 64 void generate( BaseSyntaxNode * node, std::ostream & os ) { 65 65 if ( Type * type = dynamic_cast< Type * >( node ) ) { 66 os << CodeGen::genPrettyType( type, "" );66 os << genPrettyType( type, "" ); 67 67 } else { 68 68 PassVisitor<CodeGenerator> cgv( os, true, false, false, false ); -
src/CodeGen/OperatorTable.cc
r8c50aed ra505021 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 15 17:12:22 201713 // Update Count : 1512 // Last Modified On : Tue Feb 18 15:55:01 2020 13 // Update Count : 55 14 14 // 15 15 … … 17 17 #include <map> // for map, _Rb_tree_const_iterator, map<>::const_iterator 18 18 #include <utility> // for pair 19 using namespace std; 19 20 20 21 #include "OperatorTable.h" … … 22 23 23 24 namespace CodeGen { 24 namespace{25 const OperatorInfo tableValues[] = {26 { "?[?]", "", "_operator_index", OT_INDEX},27 { "?{}", "=", "_constructor", OT_CTOR},28 { "^?{}", "", "_destructor", OT_DTOR},29 { "?()", "", "_operator_call", OT_CALL},30 { "?++", "++", "_operator_postincr", OT_POSTFIXASSIGN},31 { "?--", "--", "_operator_postdecr", OT_POSTFIXASSIGN},32 { "*?", "*", "_operator_deref", OT_PREFIX},33 { "+?", "+", "_operator_unaryplus", OT_PREFIX},34 { "-?", "-", "_operator_unaryminus", OT_PREFIX},35 { "~?", "~", "_operator_bitnot", OT_PREFIX},36 { "!?", "!", "_operator_lognot", OT_PREFIX},37 { "++?", "++", "_operator_preincr", OT_PREFIXASSIGN},38 { "--?", "--", "_operator_predecr", OT_PREFIXASSIGN},39 { "?\\?", "\\", "_operator_exponential", OT_INFIX},40 { "?*?", "*", "_operator_multiply", OT_INFIX},41 { "?/?", "/", "_operator_divide", OT_INFIX},42 { "?%?", "%", "_operator_modulus", OT_INFIX},43 { "?+?", "+", "_operator_add", OT_INFIX},44 { "?-?", "-", "_operator_subtract", OT_INFIX},45 { "?<<?", "<<", "_operator_shiftleft", OT_INFIX},46 { "?>>?", ">>", "_operator_shiftright", OT_INFIX},47 { "?<?", "<", "_operator_less", OT_INFIX &n