Changes in / [b738974:5695645]
- Files:
-
- 2 deleted
- 8 edited
-
benchmark/plot.py (modified) (3 diffs)
-
benchmark/process-mutilate.py (modified) (7 diffs)
-
benchmark/readyQ/churn.cfa (modified) (1 diff)
-
benchmark/readyQ/churn.cpp (deleted)
-
benchmark/readyQ/churn.go (deleted)
-
benchmark/readyQ/yield.cfa (modified) (1 diff)
-
benchmark/readyQ/yield.cpp (modified) (1 diff)
-
benchmark/readyQ/yield.rs (modified) (1 diff)
-
benchmark/rmit.py (modified) (5 diffs)
-
src/ControlStruct/MultiLevelExit.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
benchmark/plot.py
rb738974 r5695645 33 33 "Ops per threads" : Field('Ops' , 0, False), 34 34 "ns per ops/procs" : Field('ns' , 0, False), 35 "Number of threads" : Field(' ', 1, False),35 "Number of threads" : Field('thrd' , 1, False), 36 36 "Total Operations(ops)" : Field('Ops' , 0, False), 37 37 "Ops/sec/procs" : Field('Ops' , 0, False), … … 40 40 "Cycle size (# thrds)" : Field('thrd' , 1, False), 41 41 "Duration (ms)" : Field('ms' , 0, False), 42 "Target QPS" : Field('' , 0, False), 43 "Actual QPS" : Field('' , 0, False), 44 "Average Read Latency" : Field('us' , 0, True), 42 "Target QPS" : Field('QPS' , 0, False), 43 "Actual QPS" : Field('QPS' , 0, False), 45 44 "Median Read Latency" : Field('us' , 0, True), 46 45 "Tail Read Latency" : Field('us' , 0, True), 47 "Average Update Latency": Field('us' , 0, True),48 46 "Median Update Latency" : Field('us' , 0, True), 49 47 "Tail Update Latency" : Field('us' , 0, True), 50 "Update Ratio" : Field('\%' , 0, False),51 48 } 52 49 … … 95 92 print("Making Plots") 96 93 97 for name, data in s orted(series.items()):94 for name, data in series.items(): 98 95 _col = next(colors) 99 96 plt.scatter(data['x'], data['y'], color=_col, label=name, marker='x') -
benchmark/process-mutilate.py
rb738974 r5695645 14 14 parser = argparse.ArgumentParser(description='Python Script to convert output from mutilate to rmit like output') 15 15 parser.add_argument('--out', nargs='?', type=argparse.FileType('w'), default=sys.stdout) 16 parser.add_argument('--var', nargs='?', type=str, default='Target QPS')17 16 try: 18 17 options = parser.parse_args() … … 32 31 33 32 try: 34 latAvs = fields[6]35 33 lat50s = fields[6] 36 34 lat99s = fields[9] … … 39 37 40 38 try: 41 latAv = locale.atof(latAvs)42 39 lat50 = locale.atof(lat50s) 43 40 lat99 = locale.atof(lat99s) … … 61 58 try: 62 59 if line.startswith("read"): 63 rlat Av, rlat50, rlat99 = precentile(line)60 rlat50, rlat99 = precentile(line) 64 61 65 62 elif line.startswith("update"): 66 ulat Av, ulat50, ulat99 = precentile(line)63 ulat50, ulat99 = precentile(line) 67 64 68 65 elif line.startswith("Total QPS"): … … 87 84 88 85 try: 89 out['Average Read Latency'] = rlatAv90 86 out['Median Read Latency'] = rlat50 91 87 out['Tail Read Latency'] = rlat99 … … 94 90 95 91 try: 96 out['Average Update Latency'] = ulatAv97 92 out['Median Update Latency'] = ulat50 98 93 out['Tail Update Latency'] = ulat99 … … 117 112 continue 118 113 119 d = { options.var: int(rate) }114 d = { 'Target QPS': int(rate) } 120 115 121 116 w = extract( f, d ) -
benchmark/readyQ/churn.cfa
rb738974 r5695645 44 44 { 's', "spots", "Number of spots in the system", spot_cnt } 45 45 }; 46 BENCH_OPT_PARSE("cforall c hurnbenchmark");46 BENCH_OPT_PARSE("cforall cycle benchmark"); 47 47 48 48 { -
benchmark/readyQ/yield.cfa
rb738974 r5695645 1 #include "rq_bench.hfa" 1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <string.h> 4 #include <limits.h> 5 6 extern "C" { 7 #include <locale.h> 8 #include <getopt.h> 9 } 10 11 #include <unistd.h> 12 13 #include <clock.hfa> 14 #include <time.hfa> 15 #include <stats.hfa> 16 17 #include "../benchcltr.hfa" 18 19 extern bool traceHeapOn(); 20 21 22 volatile bool run = false; 23 volatile unsigned long long global_counter; 2 24 3 25 thread __attribute__((aligned(128))) Yielder { 4 unsigned long long count ;26 unsigned long long counter; 5 27 }; 6 28 void ?{}( Yielder & this ) { 7 ((thread&)this){ "Yielder Thread", bench_cluster };8 this.count = 0;29 this.counter = 0; 30 ((thread&)this){ "Yielder Thread", *the_benchmark_cluster }; 9 31 } 10 32 11 33 void main( Yielder & this ) { 12 34 park(); 13 for() { 35 /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) ); 36 37 while(__atomic_load_n(&run, __ATOMIC_RELAXED)) { 14 38 yield(); 15 this.count++; 16 if( clock_mode && stop) break; 17 if(!clock_mode && this.count >= stop_count) break; 39 this.counter++; 18 40 } 19 20 __atomic_fetch_add(&threads_left, -1, __ATOMIC_SEQ_CST); 41 __atomic_fetch_add(&global_counter, this.counter, __ATOMIC_SEQ_CST); 21 42 } 22 43 23 44 int main(int argc, char * argv[]) { 45 unsigned num_io = 1; 46 io_context_params params; 47 24 48 cfa_option opt[] = { 25 BENCH_OPT 49 BENCH_OPT_CFA 26 50 }; 27 BENCH_OPT_PARSE("cforall yield benchmark"); 51 int opt_cnt = sizeof(opt) / sizeof(cfa_option); 52 53 char **left; 54 parse_args( argc, argv, opt, opt_cnt, "[OPTIONS]...\ncforall yield benchmark", left ); 28 55 29 56 { 30 unsigned long long global_counter = 0;57 printf("Running %d threads on %d processors for %f seconds\n", nthreads, nprocs, duration); 31 58 32 59 Time start, end; 33 BenchCluster bc = { nprocs};60 BenchCluster cl = { num_io, params, CFA_STATS_READY_Q }; 34 61 { 35 threads_left = nthreads; 36 Yielder threads[nthreads]; 37 printf("Starting\n"); 62 BenchProc procs[nprocs]; 63 { 64 Yielder threads[nthreads]; 65 printf("Starting\n"); 38 66 39 bool is_tty = isatty(STDOUT_FILENO); 40 start = timeHiRes(); 67 bool is_tty = isatty(STDOUT_FILENO); 68 start = timeHiRes(); 69 run = true; 41 70 42 for(i; nthreads) {43 unpark( threads[i] );44 }45 wait(start, is_tty);71 for(i; nthreads) { 72 unpark( threads[i] ); 73 } 74 wait(duration, start, end, is_tty); 46 75 47 stop = true; 48 end = timeHiRes(); 49 printf("\nDone\n"); 50 51 for(i; nthreads) { 52 Yielder & y = join( threads[i] ); 53 global_counter += y.count; 76 run = false; 77 end = timeHiRes(); 78 printf("\nDone\n"); 54 79 } 55 80 } 56 81 57 printf("Duration (ms) : %'ld\n", (end - start)`dms); 58 printf("Number of processors : %'d\n", nprocs); 59 printf("Number of threads : %'d\n", nthreads); 60 printf("Total Operations(ops): %'15llu\n", global_counter); 61 printf("Ops per second : %'18.2lf\n", ((double)global_counter) / (end - start)`s); 62 printf("ns per ops : %'18.2lf\n", (end - start)`dns / global_counter); 63 printf("Ops per threads : %'15llu\n", global_counter / nthreads); 64 printf("Ops per procs : %'15llu\n", global_counter / nprocs); 65 printf("Ops/sec/procs : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s); 66 printf("ns per ops/procs : %'18.2lf\n", (end - start)`dns / (global_counter / nprocs)); 82 printf("Duration (ms) : %'ld\n", (end - start)`dms); 83 printf("Number of processors: %'d\n", nprocs); 84 printf("Number of threads : %'d\n", nthreads); 85 printf("Total yields : %'15llu\n", global_counter); 86 printf("Yields per second : %'18.2lf\n", ((double)global_counter) / (end - start)`s); 87 printf("ns per yields : %'18.2lf\n", ((double)(end - start)`ns) / global_counter); 88 printf("Yields per procs : %'15llu\n", global_counter / nprocs); 89 printf("Yields/sec/procs : %'18.2lf\n", (((double)global_counter) / nprocs) / (end - start)`s); 90 printf("ns per yields/procs : %'18.2lf\n", ((double)(end - start)`ns) / (global_counter / nprocs)); 67 91 fflush(stdout); 68 92 } -
benchmark/readyQ/yield.cpp
rb738974 r5695645 1 #include "rq_bench.hpp" 2 #include <libfibre/fibre.h> 1 #include <cassert> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <climits> 6 7 extern "C" { 8 #include <locale.h> 9 #include <getopt.h> 10 } 11 12 #include <unistd.h> 13 14 #include <chrono> 15 16 using Clock = std::chrono::high_resolution_clock; 17 using duration_t = std::chrono::duration<double>; 18 using std::chrono::nanoseconds; 19 20 21 template<typename Ratio, typename T> 22 T duration_cast(T seconds) { 23 return std::chrono::duration_cast<std::chrono::duration<T, Ratio>>(std::chrono::duration<T>(seconds)).count(); 24 } 3 25 4 26 volatile bool run = false; 5 27 volatile unsigned long long global_counter; 6 28 29 #include "libfibre/fibre.h" 7 30 8 void fibre_main() { 9 fibre_park(); 10 unsigned long long count = 0; 11 for(;;) { 31 FredBarrier * barrier; 32 struct __attribute__((aligned(128))) counter_t { 33 int value = 0; 34 }; 35 36 void fibre_main( counter_t * counter ) { 37 barrier->wait(); 38 // /* paranoid */ assert( true == __atomic_load_n(&run, __ATOMIC_RELAXED) ); 39 40 while(__atomic_load_n(&run, __ATOMIC_RELAXED)) { 12 41 Fibre::forceYield(); 13 count++; 14 if( clock_mode && stop) break; 15 if(!clock_mode && count >= stop_count) break; 42 // fibre_yield(); 43 counter->value++; 16 44 } 17 18 __atomic_fetch_add(&global_counter, count, __ATOMIC_SEQ_CST); 19 __atomic_fetch_add(&threads_left, -1, __ATOMIC_SEQ_CST); 45 __atomic_fetch_add(&global_counter, counter->value, __ATOMIC_SEQ_CST); 20 46 } 21 47 22 48 int main(int argc, char * argv[]) { 23 option_t opt[] = { 24 BENCH_OPT 25 }; 26 BENCH_OPT_PARSE("libfibre yield benchmark"); 49 double duration = 5; 50 int nprocs = 1; 51 int nthreads = 1; 52 53 std::cout.imbue(std::locale("")); 54 setlocale(LC_ALL, ""); 55 56 for(;;) { 57 static struct option options[] = { 58 {"duration", required_argument, 0, 'd'}, 59 {"nprocs", required_argument, 0, 'p'}, 60 {"nthreads", required_argument, 0, 't'}, 61 {0, 0, 0, 0} 62 }; 63 64 int idx = 0; 65 int opt = getopt_long(argc, argv, "d:p:t:", options, &idx); 66 67 const char * arg = optarg ? optarg : ""; 68 char * end; 69 switch(opt) { 70 case -1: 71 goto run; 72 // Numeric Arguments 73 case 'd': 74 duration = strtod(arg, &end); 75 if(*end != '\0') { 76 fprintf(stderr, "Duration must be a valid double, was %s\n", arg); 77 goto usage; 78 } 79 break; 80 case 't': 81 nthreads = strtoul(arg, &end, 10); 82 if(*end != '\0' || nthreads < 1) { 83 fprintf(stderr, "Number of threads must be a positive integer, was %s\n", arg); 84 goto usage; 85 } 86 break; 87 case 'p': 88 nprocs = strtoul(arg, &end, 10); 89 if(*end != '\0' || nprocs < 1) { 90 fprintf(stderr, "Number of processors must be a positive integer, was %s\n", arg); 91 goto usage; 92 } 93 break; 94 // Other cases 95 default: /* ? */ 96 fprintf( stderr, "Unkown option '%c'\n", opt); 97 usage: 98 fprintf( stderr, "Usage: %s [options]\n", argv[0]); 99 fprintf( stderr, "\n" ); 100 fprintf( stderr, " -d, --duration=DURATION Duration of the experiment, in seconds\n" ); 101 fprintf( stderr, " -t, --nthreads=NTHREADS Number of kernel threads\n" ); 102 fprintf( stderr, " -q, --nqueues=NQUEUES Number of queues per threads\n" ); 103 exit(1); 104 } 105 } 106 run: 27 107 28 108 { 29 109 printf("Running %d threads on %d processors for %lf seconds\n", nthreads, nprocs, duration); 30 110 31 FibreInit( 1, nprocs);32 uint64_t start, end;111 FibreInit(); 112 barrier = new FredBarrier(nthreads + 1); 33 113 { 34 threads_left = nthreads; 35 Fibre * threads[nthreads]; 36 for(unsigned i = 0; i < nthreads; i++) { 37 threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(fibre_main), nullptr ); 38 } 39 printf("Starting\n"); 40 bool is_tty = isatty(STDOUT_FILENO); 41 start = timeHiRes(); 114 Context::CurrCluster().addWorkers(nprocs); 115 { 116 counter_t counters[nthreads]; 117 Fibre threads[nthreads]; 118 for(int i = 0; i < nthreads; i++) { 119 threads[i].run(fibre_main, &counters[i]); 120 } 121 printf("Starting\n"); 122 bool is_tty = isatty(STDOUT_FILENO); 123 auto before = Clock::now(); 124 run = true; 42 125 43 for(unsigned i = 0; i < nthreads; i++ ) { 44 fibre_unpark( threads[i] ); 45 } 46 wait<Fibre>(start, is_tty); 126 barrier->wait(); 127 for(;;) { 128 usleep(500'000); 129 auto now = Clock::now(); 130 duration_t durr = now - before; 131 if( durr.count() > duration ) { 132 break; 133 } 134 if(is_tty) { 135 std::cout << "\r" << std::setprecision(4) << durr.count(); 136 std::cout.flush(); 137 } 138 } 47 139 48 stop = true; 49 end = timeHiRes(); 50 for(unsigned i = 0; i < nthreads; i++ ) { 51 fibre_join( threads[i], nullptr ); 140 auto after = Clock::now(); 141 duration_t durr = after - before; 142 duration = durr.count(); 143 run = false; 144 printf("\nDone\n"); 145 for(auto & thread : threads) { 146 thread.join(); 147 } 148 149 // for(const auto & counter : counters) { 150 // std::cout << counter.value << std::endl; 151 // } 52 152 } 53 153 } 54 154 55 printf("Duration (ms) : %'ld\n", to_miliseconds(end - start));56 printf("Number of processors : %'d\n", nprocs);57 printf("Number of threads : %'d\n", nthreads); 58 printf(" Total Operations(ops): %'15llu\n", global_counter);59 printf(" Ops per second : %'18.2lf\n", ((double)global_counter) / to_fseconds(end - start));60 printf(" ns per ops : %'18.2lf\n", ((double)(end - start)) / global_counter);61 printf(" Ops per threads : %'15llu\n", global_counter / nthreads);62 printf(" Ops per procs : %'15llu\n", global_counter / nprocs);63 printf(" Ops/sec/procs : %'18.2lf\n", (((double)global_counter) / nprocs) / to_fseconds(end - start));64 printf("ns per ops/procs : %'18.2lf\n", ((double)(end - start)) / (global_counter / nprocs));65 fflush(stdout); 155 auto dur_nano = duration_cast<std::nano>(duration); 156 auto dur_dms = duration_cast<std::milli>(duration); 157 158 printf("Duration (ms) : %'.2lf\n", dur_dms ); 159 printf("Total yields : %'15llu\n", global_counter ); 160 printf("Yields per procs : %'15llu\n", global_counter / nprocs ); 161 printf("Yields per second : %'18.2lf\n", ((double)global_counter) / duration ); 162 printf("Yields/sec/procs : %'18.2lf\n", (((double)global_counter) / nprocs) / duration ); 163 printf("ns per yields : %'18.2lf\n", dur_nano / global_counter ); 164 printf("ns per yields/procs : %'18.2lf\n", dur_nano / (global_counter / nprocs) ); 165 66 166 } 67 167 } -
benchmark/readyQ/yield.rs
rb738974 r5695645 90 90 }); 91 91 92 println!("Duration (ms) : {}", (duration.as_millis()).to_formatted_string(&Locale::en));93 println!("Number of processors : {}", (nprocs).to_formatted_string(&Locale::en));94 println!("Number of threads : {}", (nthreads).to_formatted_string(&Locale::en));95 println!("Total Operations(ops): {:>15}", (global_counter).to_formatted_string(&Locale::en));96 println!(" Ops per second: {:>15}", (((global_counter as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en));97 println!("ns per ops: {:>15}", ((duration.as_nanos() as f64 / global_counter as f64) as u64).to_formatted_string(&Locale::en));98 println!(" Ops per threads: {:>15}", (global_counter / nthreads as u64).to_formatted_string(&Locale::en));99 println!(" Ops per procs: {:>15}", (global_counter / nprocs as u64).to_formatted_string(&Locale::en));100 println!(" Ops/sec/procs: {:>15}", ((((global_counter as f64) / nprocs as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en));101 println!("ns per ops/procs: {:>15}", ((duration.as_nanos() as f64 / (global_counter as f64 / nprocs as f64)) as u64).to_formatted_string(&Locale::en));92 println!("Duration (ms) : {}", (duration.as_millis()).to_formatted_string(&Locale::en)); 93 println!("Number of processors: {}", (nprocs).to_formatted_string(&Locale::en)); 94 println!("Number of threads : {}", (nthreads).to_formatted_string(&Locale::en)); 95 println!("Total yields : {:>15}", (global_counter).to_formatted_string(&Locale::en)); 96 println!("Yields per second : {:>15}", (((global_counter as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en)); 97 println!("ns per yields : {:>15}", ((duration.as_nanos() as f64 / global_counter as f64) as u64).to_formatted_string(&Locale::en)); 98 println!("Yields per threads : {:>15}", (global_counter / nthreads as u64).to_formatted_string(&Locale::en)); 99 println!("Yields per procs : {:>15}", (global_counter / nprocs as u64).to_formatted_string(&Locale::en)); 100 println!("Yields/sec/procs : {:>15}", ((((global_counter as f64) / nprocs as f64) / duration.as_secs() as f64) as u64).to_formatted_string(&Locale::en)); 101 println!("ns per yields/procs : {:>15}", ((duration.as_nanos() as f64 / (global_counter as f64 / nprocs as f64)) as u64).to_formatted_string(&Locale::en)); 102 102 } -
benchmark/rmit.py
rb738974 r5695645 63 63 return eval(fmt) 64 64 65 # Evaluate all the options66 # options can be of the for key = val or key = some_math(other_key)67 # produce a list of all the options to replace some_math(other_key) with actual value68 65 def eval_options(opts): 69 # Find all the options with dependencies70 66 dependents = [d for d in opts.values() if type(d) is DependentOpt] 71 72 # we need to find all the straglers73 67 processed = [] 74 75 # extract all the necessary inputs 76 input_keys = {} 68 nopts = [] 77 69 for d in dependents: 78 # Mark the dependent as seen79 70 processed.append(d.key) 80 81 # process each of the dependencies 71 lists = [] 82 72 for dvar in d.vars: 83 # Check that it depends on something that exists84 73 if not dvar in opts.keys(): 85 74 print('ERROR: extra pattern option {}:{} uses unknown key {}'.format(d.key,d.value,dvar), file=sys.stderr) 86 75 sys.exit(1) 87 76 88 # Check that it's not nested 89 if type(dvar) is DependentOpt: 90 print('ERROR: dependent options cannot be nested {}:{} uses key {}'.format(d.key,d.value,dvar), file=sys.stderr) 91 sys.exit(1) 92 93 # Add the values to the input keys 94 if dvar not in input_keys: 95 input_keys[dvar] = opts[dvar] 96 else : 97 if input_keys[dvar] != opts[dvar]: 98 print('INTERNAL ERROR: repeat input do not match {}:{} vs {}'.format(dvar,opts[dvar],input_keys[dvar]), file=sys.stderr) 99 sys.exit(1) 100 101 # Mark the input as seen 77 lists.append([(dvar, o) for o in opts[dvar]]) 102 78 processed.append(dvar) 103 79 104 # add in all the straglers they should cause too many problems 105 for k, v in opts.items(): 106 if type(v) is DependentOpt: 107 continue 108 109 if k in processed: 110 # consistency check 111 if k not in input_keys: 112 print('INTERNAL ERROR: key \'{}\' marked as processed but not in input_keys'.format(k), file=sys.stderr) 113 sys.exit(1) 114 continue 115 116 # consistency check 117 if k in input_keys: 118 print('INTERNAL ERROR: key \'{}\' in input_keys but not marked as processed'.format(k), file=sys.stderr) 119 sys.exit(1) 120 121 # add the straggler 122 input_keys[k] = v 123 124 # flatten the dict into a list of pairs so it's easier to work with 125 input_list = [] 126 for k, v in input_keys.items(): 127 input_list.append([(k, o) for o in v]) 128 129 # evaluate all the dependents 130 # they are not allowed to produce new values so it's a one-to-one mapping from here 131 evaluated = [] 132 for inputs in list(itertools.product(*input_list)): 133 this_eval = list(inputs) 134 for d in dependents: 135 this_eval.append((d.key, eval_one(d.value, inputs))) 136 137 evaluated.append(this_eval) 138 139 # reformat everything to a list of arguments 140 formated = [] 141 for o in evaluated: 142 inner = [] 143 for k,v in o: 144 inner.append("-{}".format(k)) 145 inner.append("{}".format(v)) 146 147 # print(inner) 148 formated.append(inner) 149 150 return formated 80 kopt = [] 81 for vals in list(itertools.product(*lists)): 82 res = ['-{}'.format(d.key), "{}".format(eval_one(d.value, vals))] 83 for k, v in vals: 84 res.extend(['-{}'.format(k), "{}".format(v)]) 85 kopt.append(res) 86 nopts.append(kopt) 87 88 89 for k, vals in opts.items(): 90 if k not in processed: 91 kopt = [] 92 for v in vals: 93 kopt.append(['-{}'.format(k), "{}".format(v)]) 94 nopts.append(kopt) 95 96 return nopts 151 97 152 98 # returns the first option with key 'opt' … … 176 122 known_hosts = { 177 123 "jax": { 178 range( 1, 2 5) : "48-71",179 range( 25, 4 9) : "48-71,144-167",180 range( 49, 9 7) : "48-95,144-191",181 range( 97, 14 5) : "24-95,120-191",182 range(145, 19 3) : "0-95,96-191",124 range( 1, 24) : "48-71", 125 range( 25, 48) : "48-71,144-167", 126 range( 49, 96) : "48-95,144-191", 127 range( 97, 144) : "24-95,120-191", 128 range(145, 192) : "0-95,96-191", 183 129 }, 184 130 } … … 238 184 239 185 except: 186 print('ERROR: invalid arguments', file=sys.stderr) 187 parser.print_help(sys.stderr) 240 188 sys.exit(1) 241 189 … … 267 215 # Figure out all the combinations to run 268 216 actions = [] 269 for p in itertools.product(range(options.trials), commands, opts):217 for p in itertools.product(range(options.trials), commands, *opts): 270 218 act = [p[1]] 271 219 for o in p[2:]: … … 333 281 334 282 if options.file != sys.stdout: 335 print("Done ")283 print("Done"); ") -
src/ControlStruct/MultiLevelExit.cpp
rb738974 r5695645 594 594 } 595 595 596 // check if loop node and if so add else clause if it exists597 const WhileDoStmt * whilePtr = dynamic_cast<const WhileDoStmt *>(kid.get());598 if ( whilePtr && whilePtr->else_) ret.push_back(whilePtr->else_);599 const ForStmt * forPtr = dynamic_cast<const ForStmt *>(kid.get());600 if ( forPtr && forPtr->else_) ret.push_back(forPtr->else_);601 602 596 if ( ! break_label.empty() ) { 603 597 ret.push_back( labelledNullStmt( ret.back()->location, break_label ) );
Note:
See TracChangeset
for help on using the changeset viewer.