Changeset e5628db
- Timestamp:
- May 12, 2022, 3:10:58 PM (19 months ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation, qualifiedEnum
- Children:
- 8060b2b, f835806
- Parents:
- f75e25b (diff), 491bb81 (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:
-
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
benchmark/process-mutilate.py
rf75e25b re5628db 32 32 33 33 try: 34 latAvs = fields[ 6]34 latAvs = fields[1] 35 35 lat50s = fields[6] 36 36 lat99s = fields[9] … … 45 45 raise Warning("Warning: \"{}\" \"{}\"! can't convert to float".format(lat50s, lat99s)) 46 46 47 return lat 50, lat9947 return latAv, lat50, lat99 48 48 49 49 def want0(line): -
benchmark/readyQ/bench.go
rf75e25b re5628db 71 71 duration = 5 72 72 clock_mode = true 73 fmt.Printf("Running for %f seconds \n", duration)73 fmt.Printf("Running for %f seconds (default)\n", duration) 74 74 } 75 75 -
benchmark/readyQ/churn.cpp
rf75e25b re5628db 54 54 Fibre * threads[nthreads]; 55 55 for(unsigned i = 0; i < nthreads; i++) { 56 threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(churner_main), &thddata[i] ); 56 threads[i] = new Fibre(); 57 threads[i]->run(churner_main, &thddata[i]); 57 58 } 58 59 printf("Starting\n"); -
benchmark/readyQ/cycle.cpp
rf75e25b re5628db 46 46 } 47 47 for(unsigned i = 0; i < tthreads; i++) { 48 threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(partner_main), &thddata[i] ); 48 threads[i] = new Fibre(); 49 threads[i]->run( partner_main, &thddata[i] ); 49 50 } 50 51 printf("Starting\n"); -
benchmark/readyQ/rq_bench.hpp
rf75e25b re5628db 143 143 } 144 144 145 if(strcmp(arg, "Y") == 0) { 146 value = true; 147 return true; 148 } 149 150 if(strcmp(arg, "y") == 0) { 151 value = true; 152 return true; 153 } 154 145 155 if(strcmp(arg, "no") == 0) { 156 value = false; 157 return true; 158 } 159 160 if(strcmp(arg, "N") == 0) { 161 value = false; 162 return true; 163 } 164 165 if(strcmp(arg, "n") == 0) { 146 166 value = false; 147 167 return true; -
benchmark/readyQ/transfer.cfa
rf75e25b re5628db 14 14 15 15 bool exhaust = false; 16 volatile bool estop = false; 17 16 18 17 19 thread$ * the_main; … … 35 37 static void waitgroup() { 36 38 Time start = timeHiRes(); 37 for(i; nthreads) {39 OUTER: for(i; nthreads) { 38 40 PRINT( sout | "Waiting for :" | i | "(" | threads[i]->idx | ")"; ) 39 41 while( threads[i]->idx != lead_idx ) { … … 42 44 print_stats_now( bench_cluster, CFA_STATS_READY_Q | CFA_STATS_IO ); 43 45 serr | "Programs has been blocked for more than 5 secs"; 44 exit(1); 46 estop = true; 47 unpark( the_main ); 48 break OUTER; 45 49 } 46 50 } … … 59 63 static void lead(MyThread & this) { 60 64 this.idx = ++lead_idx; 61 if(lead_idx > stop_count ) {65 if(lead_idx > stop_count || estop) { 62 66 PRINT( sout | "Leader" | this.id | "done"; ) 63 67 unpark( the_main ); … … 100 104 wait( this ); 101 105 } 102 if(lead_idx > stop_count ) break;106 if(lead_idx > stop_count || estop) break; 103 107 } 104 108 } … … 172 176 sout | "Number of processors : " | nprocs; 173 177 sout | "Number of threads : " | nthreads; 174 sout | "Total Operations(ops) : " | stop_count;178 sout | "Total Operations(ops) : " | lead_idx - 1; 175 179 sout | "Threads parking on wait : " | (exhaust ? "yes" : "no"); 176 180 sout | "Rechecking : " | rechecks; 181 sout | "ns per transfer : " | (end - start)`dms / lead_idx; 177 182 178 183 -
benchmark/readyQ/transfer.cpp
rf75e25b re5628db 12 12 13 13 bool exhaust = false; 14 volatile bool estop = false; 14 15 15 16 bench_sem the_main; … … 42 43 if( to_miliseconds(timeHiRes() - start) > 5'000 ) { 43 44 std::cerr << "Programs has been blocked for more than 5 secs" << std::endl; 44 std::exit(1); 45 estop = true; 46 the_main.post(); 47 goto END; 45 48 } 46 49 } 47 50 } 51 END:; 48 52 PRINT( std::cout | "Waiting done"; ) 49 53 } … … 59 63 void lead() { 60 64 this->idx = ++lead_idx; 61 if(lead_idx > stop_count ) {65 if(lead_idx > stop_count || estop) { 62 66 PRINT( std::cout << "Leader " << this->id << " done" << std::endl; ) 63 67 the_main.post(); … … 88 92 } 89 93 90 static void main( void * arg) {91 MyThread & self = * reinterpret_cast<MyThread*>(arg);94 static void main(MyThread * arg) { 95 MyThread & self = *arg; 92 96 self.park(); 93 97 … … 101 105 self.wait(); 102 106 } 103 if(lead_idx > stop_count ) break;107 if(lead_idx > stop_count || estop) break; 104 108 } 105 109 } … … 144 148 for(size_t i = 0; i < nthreads; i++) { 145 149 threads[i] = new MyThread( i ); 146 handles[i] = new Fibre( MyThread::main, threads[i] ); 150 handles[i] = new Fibre(); 151 handles[i]->run( MyThread::main, threads[i] ); 147 152 } 148 153 … … 164 169 PRINT( std::cout << i << " joined" << std::endl; ) 165 170 rechecks += thrd.rechecks; 166 // delete( handles[i] );167 171 delete( threads[i] ); 168 172 } … … 176 180 std::cout << "Number of processors : " << nprocs << std::endl; 177 181 std::cout << "Number of threads : " << nthreads << std::endl; 178 std::cout << "Total Operations(ops) : " << stop_count<< std::endl;182 std::cout << "Total Operations(ops) : " << (lead_idx - 1) << std::endl; 179 183 std::cout << "Threads parking on wait : " << (exhaust ? "yes" : "no") << std::endl; 180 184 std::cout << "Rechecking : " << rechecks << std::endl; 185 std::cout << "ns per transfer : " << std::fixed << (((double)(end - start)) / (lead_idx)) << std::endl; 181 186 182 187 -
benchmark/readyQ/transfer.go
rf75e25b re5628db 6 6 "math/rand" 7 7 "os" 8 "regexp" 8 9 "runtime" 9 10 "sync/atomic" … … 16 17 id uint64 17 18 idx uint64 19 estop uint64 18 20 seed uint64 19 21 } … … 34 36 35 37 func NewLeader(size uint64) (*LeaderInfo) { 36 this := &LeaderInfo{0, 0, uint64(os.Getpid())}38 this := &LeaderInfo{0, 0, 0, uint64(os.Getpid())} 37 39 38 40 r := rand.Intn(10) … … 51 53 } 52 54 53 func waitgroup( idx uint64, threads [] MyThread) {55 func waitgroup(leader * LeaderInfo, idx uint64, threads [] MyThread, main_sem chan struct {}) { 54 56 start := time.Now() 57 Outer: 55 58 for i := 0; i < len(threads); i++ { 56 59 // fmt.Fprintf(os.Stderr, "Waiting for :%d (%d)\n", threads[i].id, atomic.LoadUint64(&threads[i].idx) ); … … 61 64 if delta.Seconds() > 5 { 62 65 fmt.Fprintf(os.Stderr, "Programs has been blocked for more than 5 secs") 63 os.Exit(1) 66 atomic.StoreUint64(&leader.estop, 1); 67 main_sem <- (struct {}{}) 68 break Outer 64 69 } 65 70 } … … 74 79 if i != me { 75 80 // debug!( "Leader waking {}", i); 81 defer func() { 82 if err := recover(); err != nil { 83 fmt.Fprintf(os.Stderr, "Panic occurred: %s\n", err) 84 } 85 }() 76 86 threads[i].sem <- (struct {}{}) 77 87 } … … 84 94 atomic.StoreUint64(&leader.idx, nidx); 85 95 86 if nidx > stop_count {96 if nidx > stop_count || atomic.LoadUint64(&leader.estop) != 0 { 87 97 // debug!( "Leader {} done", this.id); 88 98 main_sem <- (struct {}{}) … … 92 102 // debug!( "====================\nLeader no {} : {}", nidx, this.id); 93 103 94 waitgroup( nidx, threads);104 waitgroup(leader, nidx, threads, main_sem); 95 105 96 106 leader.next( uint64(len(threads)) ); … … 146 156 waitleader( exhaust, leader, &threads[me], &r ) 147 157 } 148 if atomic.LoadUint64(&leader.idx) > stop_count { break; }158 if atomic.LoadUint64(&leader.idx) > stop_count || atomic.LoadUint64(&leader.estop) != 0 { break; } 149 159 } 150 160 … … 155 165 func main() { 156 166 // Benchmark specific command line arguments 157 exhaustOpt := flag. Bool("e", false, "Whether or not threads that have seen the new epoch should park instead of yielding.")167 exhaustOpt := flag.String("e", "no", "Whether or not threads that have seen the new epoch should park instead of yielding.") 158 168 159 169 // General benchmark initialization and deinitialization 160 defer bench_init()() 161 162 exhaust := *exhaustOpt; 170 bench_init() 171 172 exhaustVal := *exhaustOpt; 173 174 var exhaust bool 175 re_yes := regexp.MustCompile("[Yy]|[Yy][Ee][Ss]") 176 re_no := regexp.MustCompile("[Nn]|[Nn][Oo]") 177 if re_yes.Match([]byte(exhaustVal)) { 178 exhaust = true 179 } else if re_no.Match([]byte(exhaustVal)) { 180 exhaust = false 181 } else { 182 fmt.Fprintf(os.Stderr, "Unrecognized exhaust(-e) option '%s'\n", exhaustVal) 183 os.Exit(1) 184 } 185 163 186 if clock_mode { 164 fmt.Fprintf(os.Stderr, "Programs does not support fixed duration mode ")187 fmt.Fprintf(os.Stderr, "Programs does not support fixed duration mode\n") 165 188 os.Exit(1) 166 189 } … … 215 238 ws = "no" 216 239 } 217 p.Printf("Duration (ms) : % f\n", delta.Milliseconds() )240 p.Printf("Duration (ms) : %d\n", delta.Milliseconds() ) 218 241 p.Printf("Number of processors : %d\n", nprocs ) 219 242 p.Printf("Number of threads : %d\n", nthreads ) 220 p.Printf("Total Operations(ops) : %15d\n", stop_count)243 p.Printf("Total Operations(ops) : %15d\n", (leader.idx - 1) ) 221 244 p.Printf("Threads parking on wait : %s\n", ws) 222 245 p.Printf("Rechecking : %d\n", rechecks ) 223 } 246 p.Printf("ns per transfer : %f\n", float64(delta.Nanoseconds()) / float64(leader.idx) ) 247 } -
benchmark/readyQ/transfer.rs
rf75e25b re5628db 6 6 use std::hint; 7 7 use std::sync::Arc; 8 use std::sync::atomic::{Atomic Usize, Ordering};8 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; 9 9 use std::time::{Instant,Duration}; 10 10 … … 44 44 match val { 45 45 "yes" => true, 46 "Y" => true, 47 "y" => true, 46 48 "no" => false, 49 "N" => false, 50 "n" => false, 47 51 "maybe" | "I don't know" | "Can you repeat the question?" => { 48 52 eprintln!("Lines for 'Malcolm in the Middle' are not acceptable values of parameter 'exhaust'"); … … 64 68 id: AtomicUsize, 65 69 idx: AtomicUsize, 70 estop: AtomicBool, 66 71 seed: u128, 67 72 } … … 72 77 id: AtomicUsize::new(nthreads), 73 78 idx: AtomicUsize::new(0), 79 estop: AtomicBool::new(false), 74 80 seed: process::id() as u128 75 81 }; … … 100 106 } 101 107 102 fn waitgroup( idx: usize, threads: &Vec<Arc<MyThread>>) {108 fn waitgroup(leader: &LeaderInfo, idx: usize, threads: &Vec<Arc<MyThread>>, main_sem: &sync::Semaphore) { 103 109 let start = Instant::now(); 104 for t in threads {110 'outer: for t in threads { 105 111 debug!( "Waiting for :{} ({})", t.id, t.idx.load(Ordering::Relaxed) ); 106 112 while t.idx.load(Ordering::Relaxed) != idx { … … 108 114 if start.elapsed() > Duration::from_secs(5) { 109 115 eprintln!("Programs has been blocked for more than 5 secs"); 110 std::process::exit(1); 116 leader.estop.store(true, Ordering::Relaxed); 117 main_sem.add_permits(1); 118 break 'outer; 111 119 } 112 120 } … … 131 139 leader.idx.store(nidx, Ordering::Relaxed); 132 140 133 if nidx as u64 > exp.stop_count {141 if nidx as u64 > exp.stop_count || leader.estop.load(Ordering::Relaxed) { 134 142 debug!( "Leader {} done", this.id); 135 143 main_sem.add_permits(1); … … 139 147 debug!( "====================\nLeader no {} : {}", nidx, this.id); 140 148 141 waitgroup( nidx, threads);149 waitgroup(leader, nidx, threads, main_sem); 142 150 143 151 leader.next( threads.len() ); … … 192 200 wait( exhaust, &leader, &threads[me], &mut rechecks ).await; 193 201 } 194 if leader.idx.load(Ordering::Relaxed) as u64 > exp.stop_count { break; }202 if leader.idx.load(Ordering::Relaxed) as u64 > exp.stop_count || leader.estop.load(Ordering::Relaxed) { break; } 195 203 } 196 204 … … 273 281 println!("Number of processors : {}", (nprocs).to_formatted_string(&Locale::en)); 274 282 println!("Number of threads : {}", (nthreads).to_formatted_string(&Locale::en)); 275 println!("Total Operations(ops) : {:>15}", ( exp.stop_count).to_formatted_string(&Locale::en));283 println!("Total Operations(ops) : {:>15}", (leader.idx.load(Ordering::Relaxed) - 1).to_formatted_string(&Locale::en)); 276 284 println!("Threads parking on wait : {}", if exhaust { "yes" } else { "no" }); 277 285 println!("Rechecking : {}", rechecks ); 278 } 286 println!("ns per transfer : {}", ((duration.as_nanos() as f64) / leader.idx.load(Ordering::Relaxed) as f64)); 287 288 } -
benchmark/readyQ/yield.cpp
rf75e25b re5628db 10 10 unsigned long long count = 0; 11 11 for(;;) { 12 Fibre:: forceYield();12 Fibre::yield(); 13 13 count++; 14 14 if( clock_mode && stop) break; … … 35 35 Fibre * threads[nthreads]; 36 36 for(unsigned i = 0; i < nthreads; i++) { 37 threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(fibre_main), nullptr ); 37 threads[i] = new Fibre(); 38 threads[i]->run(fibre_main); 38 39 } 39 40 printf("Starting\n"); -
benchmark/rmit.py
rf75e25b re5628db 46 46 pass 47 47 48 if re.search("^[0-9-,]+$", values): 48 if values.startswith('\\'): 49 return key, values[1:].split(',') 50 elif re.search("^[0-9-,]+$", values): 49 51 values = parse_range(values) 50 52 return key, [v for v in values] -
libcfa/src/concurrency/io.cfa
rf75e25b re5628db 244 244 245 245 remote = true; 246 __STATS__( false, io.calls.helped++; )246 __STATS__( true, io.calls.helped++; ) 247 247 } 248 248 proc->io.target = MAX; -
libcfa/src/concurrency/ready_subqueue.hfa
rf75e25b re5628db 83 83 /* paranoid */ verify( node->link.ts != 0 ); 84 84 /* paranoid */ verify( this.anchor.ts != 0 ); 85 /* paranoid */ verify( (this.anchor.ts == MAX) == is_empty ); 85 86 return [node, this.anchor.ts]; 86 87 } … … 93 94 // Return the timestamp 94 95 static inline unsigned long long ts(__intrusive_lane_t & this) { 95 // Cannot verify here since it may not be locked96 // Cannot verify 'emptiness' here since it may not be locked 96 97 /* paranoid */ verify(this.anchor.ts != 0); 97 98 return this.anchor.ts; -
libcfa/src/parseargs.cfa
rf75e25b re5628db 208 208 } 209 209 210 if(strcmp(arg, "Y") == 0) { 211 value = true; 212 return true; 213 } 214 215 if(strcmp(arg, "y") == 0) { 216 value = true; 217 return true; 218 } 219 210 220 if(strcmp(arg, "no") == 0) { 221 value = false; 222 return true; 223 } 224 225 if(strcmp(arg, "N") == 0) { 226 value = false; 227 return true; 228 } 229 230 if(strcmp(arg, "n") == 0) { 211 231 value = false; 212 232 return true; -
src/AST/Convert.cpp
rf75e25b re5628db 93 93 }; 94 94 95 96 97 98 95 template<typename T> 96 Getter<T> get() { 97 return Getter<T>{ *this }; 98 } 99 99 100 100 Label makeLabel(Statement * labelled, const ast::Label& label) { … … 1651 1651 // GET_ACCEPT_1(type, FunctionType), 1652 1652 std::move(forall), 1653 std::move(assertions), 1653 1654 std::move(paramVars), 1654 1655 std::move(returnVars), … … 1664 1665 cache.emplace( old, decl ); 1665 1666 1666 decl->assertions = std::move(assertions);1667 1667 decl->withExprs = GET_ACCEPT_V(withExprs, Expr); 1668 1668 decl->stmts = GET_ACCEPT_1(statements, CompoundStmt); -
src/AST/Copy.cpp
rf75e25b re5628db 10 10 // Created On : Thr Nov 11 9:16:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T hr Nov 11 9:28:00 202113 // Update Count : 012 // Last Modified On : Tue May 3 16:28:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 77 77 } 78 78 79 void postvisit( const UniqueExpr * node ) { 80 readonlyInsert( &node->object ); 81 } 82 79 83 void postvisit( const MemberExpr * node ) { 80 84 readonlyInsert( &node->member ); -
src/AST/Decl.cpp
rf75e25b re5628db 9 9 // Author : Aaron B. Moss 10 10 // Created On : Thu May 9 10:00:00 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T ue Jan 12 16:54:55 202113 // Update Count : 2 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu May 5 12:10:00 2022 13 // Update Count : 24 14 14 // 15 15 … … 53 53 // --- FunctionDecl 54 54 55 FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 55 FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 56 56 std::vector<ptr<TypeDecl>>&& forall, 57 57 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, … … 74 74 } 75 75 this->type = ftype; 76 } 77 78 FunctionDecl::FunctionDecl( const CodeLocation & location, const std::string & name, 79 std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions, 80 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 81 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 82 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs) 83 : DeclWithType( location, name, storage, linkage, std::move(attrs), fs ), 84 params( std::move(params) ), returns( std::move(returns) ), 85 type_params( std::move( forall) ), assertions( std::move( assertions ) ), 86 type( nullptr ), stmts( stmts ) { 87 FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs ); 88 for ( auto & param : this->params ) { 89 type->params.emplace_back( param->get_type() ); 90 } 91 for ( auto & ret : this->returns ) { 92 type->returns.emplace_back( ret->get_type() ); 93 } 94 for ( auto & param : this->type_params ) { 95 type->forall.emplace_back( new TypeInstType( param ) ); 96 } 97 for ( auto & assertion : this->assertions ) { 98 type->assertions.emplace_back( 99 new VariableExpr( assertion->location, assertion ) ); 100 } 101 this->type = type; 76 102 } 77 103 -
src/AST/Decl.hpp
rf75e25b re5628db 9 9 // Author : Aaron B. Moss 10 10 // Created On : Thu May 9 10:00:00 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Mar 12 18:25:05 202113 // Update Count : 3 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu May 5 12:09:00 2022 13 // Update Count : 33 14 14 // 15 15 … … 135 135 std::vector< ptr<Expr> > withExprs; 136 136 137 // The difference between the two constructors is in how they handle 138 // assertions. The first constructor uses the assertions from the type 139 // parameters, in the style of the old ast, and puts them on the type. 140 // The second takes an explicite list of assertions and builds a list of 141 // references to them on the type. 142 137 143 FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall, 138 144 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 139 145 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, 140 146 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false); 141 // : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)), 142 // stmts( stmts ) {} 147 148 FunctionDecl( const CodeLocation & location, const std::string & name, 149 std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions, 150 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 151 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, 152 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false); 143 153 144 154 const Type * get_type() const override; -
src/AST/Expr.hpp
rf75e25b re5628db 784 784 public: 785 785 ptr<Expr> expr; 786 ptr<ObjectDecl> object;786 readonly<ObjectDecl> object; 787 787 ptr<VariableExpr> var; 788 788 unsigned long long id; -
src/AST/Label.hpp
rf75e25b re5628db 34 34 std::vector< ptr<Attribute> > attributes; 35 35 36 Label( CodeLocationloc, const std::string& name = "",36 Label( const CodeLocation& loc, const std::string& name = "", 37 37 std::vector<ptr<Attribute>> && attrs = std::vector<ptr<Attribute>>{} ) 38 38 : location( loc ), name( name ), attributes( attrs ) {} -
src/AST/Node.hpp
rf75e25b re5628db 10 10 // Created On : Wed May 8 10:27:04 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 25 10:33:00 202213 // Update Count : 712 // Last Modified On : Mon May 9 10:20:00 2022 13 // Update Count : 8 14 14 // 15 15 … … 49 49 50 50 bool unique() const { return strong_count == 1; } 51 bool isManaged() const {return strong_count > 0; } 51 bool isManaged() const { return strong_count > 0; } 52 bool isReferenced() const { return weak_count > 0; } 53 bool isStable() const { 54 return (1 == strong_count || (1 < strong_count && 0 == weak_count)); 55 } 52 56 53 57 private: -
src/AST/Pass.proto.hpp
rf75e25b re5628db 131 131 template< typename node_t > 132 132 struct result1 { 133 bool differs ;134 const node_t * value ;133 bool differs = false; 134 const node_t * value = nullptr; 135 135 136 136 template< typename object_t, typename super_t, typename field_t > … … 151 151 }; 152 152 153 bool differs ;153 bool differs = false; 154 154 container_t< delta > values; 155 155 … … 167 167 template< template<class...> class container_t, typename node_t > 168 168 struct resultN { 169 bool differs ;169 bool differs = false; 170 170 container_t<ptr<node_t>> values; 171 171 -
src/AST/Stmt.cpp
rf75e25b re5628db 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed May 8 13:00:00 2019 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Feb 2 19:01:20 202213 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue May 3 15:18:20 2022 13 // Update Count : 4 14 14 // 15 15 16 16 #include "Stmt.hpp" 17 17 18 18 #include "Copy.hpp" 19 19 #include "DeclReplacer.hpp" 20 20 #include "Type.hpp" … … 23 23 24 24 // --- CompoundStmt 25 CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids(other.kids) { 25 CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids() { 26 // Statements can have weak references to them, if that happens inserting 27 // the original node into the new list will put the original node in a 28 // bad state, where it cannot be mutated. To avoid this, just perform an 29 // additional shallow copy on the statement. 30 for ( const Stmt * kid : other.kids ) { 31 if ( kid->isReferenced() ) { 32 kids.emplace_back( ast::shallowCopy( kid ) ); 33 } else { 34 kids.emplace_back( kid ); 35 } 36 } 37 26 38 // when cloning a compound statement, we may end up cloning declarations which 27 39 // are referred to by VariableExprs throughout the block. Cloning a VariableExpr -
src/AST/Stmt.hpp
rf75e25b re5628db 58 58 // cannot be, they are sub-types of this type, for organization. 59 59 60 60 StmtClause( const CodeLocation & loc ) 61 61 : ParseNode(loc) {} 62 62 … … 396 396 class WaitForClause final : public StmtClause { 397 397 public: 398 399 400 401 402 403 398 ptr<Expr> target_func; 399 std::vector<ptr<Expr>> target_args; 400 ptr<Stmt> stmt; 401 ptr<Expr> cond; 402 403 WaitForClause( const CodeLocation & loc ) 404 404 : StmtClause( loc ) {} 405 405 406 406 const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); } 407 407 private: 408 409 408 WaitForClause * clone() const override { return new WaitForClause{ *this }; } 409 MUTATE_FRIEND 410 410 }; 411 411 -
src/AST/Util.cpp
rf75e25b re5628db 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Util. hpp -- General utilities for working with the AST.7 // Util.cpp -- General utilities for working with the AST. 8 8 // 9 9 // Author : Andrew Beach 10 10 // Created On : Wed Jan 19 9:46:00 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Mar 11 18:07:00 202213 // Update Count : 112 // Last Modified On : Wed May 11 16:16:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 46 46 47 47 /// Check that every note that can has a set CodeLocation. 48 struct SetCodeLocationsCore { 49 void previsit( const ParseNode * node ) { 50 assert( node->location.isSet() ); 48 void isCodeLocationSet( const ParseNode * node ) { 49 assert( node->location.isSet() ); 50 } 51 52 void areLabelLocationsSet( const Stmt * stmt ) { 53 for ( const Label& label : stmt->labels ) { 54 assert( label.location.isSet() ); 51 55 } 52 }; 56 } 57 58 /// Make sure the reference counts are in a valid combination. 59 void isStable( const Node * node ) { 60 assert( node->isStable() ); 61 } 62 63 /// Check that a FunctionDecl is synchronized with it's FunctionType. 64 void functionDeclMatchesType( const FunctionDecl * decl ) { 65 // The type is a cache of sorts, if it is missing that is only a 66 // problem if isTypeFixed is set. 67 if ( decl->isTypeFixed ) { 68 assert( decl->type ); 69 } else if ( !decl->type ) { 70 return; 71 } 72 73 const FunctionType * type = decl->type; 74 75 // Check that `type->forall` corresponds with `decl->type_params`. 76 assert( type->forall.size() == decl->type_params.size() ); 77 // Check that `type->assertions` corresponds with `decl->assertions`. 78 assert( type->assertions.size() == decl->assertions.size() ); 79 // Check that `type->params` corresponds with `decl->params`. 80 assert( type->params.size() == decl->params.size() ); 81 // Check that `type->returns` corresponds with `decl->returns`. 82 assert( type->returns.size() == decl->returns.size() ); 83 } 53 84 54 85 struct InvariantCore { … … 56 87 // None of the passes should make changes so ordering doesn't matter. 57 88 NoStrongCyclesCore no_strong_cycles; 58 SetCodeLocationsCore set_code_locations;59 89 60 90 void previsit( const Node * node ) { 61 91 no_strong_cycles.previsit( node ); 92 isStable( node ); 62 93 } 63 94 64 95 void previsit( const ParseNode * node ) { 65 no_strong_cycles.previsit( node ); 66 set_code_locations.previsit( node ); 96 previsit( (const Node *)node ); 97 isCodeLocationSet( node ); 98 } 99 100 void previsit( const FunctionDecl * node ) { 101 previsit( (const ParseNode *)node ); 102 functionDeclMatchesType( node ); 103 } 104 105 void previsit( const Stmt * node ) { 106 previsit( (const ParseNode *)node ); 107 areLabelLocationsSet( node ); 67 108 } 68 109 -
src/Common/CodeLocationTools.cpp
rf75e25b re5628db 10 10 // Created On : Fri Dec 4 15:42:00 2020 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Mar 14 15:14:00 202213 // Update Count : 412 // Last Modified On : Wed May 11 16:16:00 2022 13 // Update Count : 5 14 14 // 15 15 … … 24 24 namespace { 25 25 26 // There are a lot of helpers in this file that could be used much more27 // generally if anyone has another use for them.28 29 // Check if a node type has a code location.30 template<typename node_t>31 struct has_code_location : public std::is_base_of<ast::ParseNode, node_t> {};32 33 template<typename node_t, bool has_location>34 struct __GetCL;35 36 template<typename node_t>37 struct __GetCL<node_t, true> {38 static inline CodeLocation const * get( node_t const * node ) {39 return &node->location;40 }41 42 static inline CodeLocation * get( node_t * node ) {43 return &node->location;44 }45 };46 47 template<typename node_t>48 struct __GetCL<node_t, false> {49 static inline CodeLocation * get( node_t const * ) {50 return nullptr;51 }52 };53 54 template<typename node_t>55 CodeLocation const * get_code_location( node_t const * node ) {56 return __GetCL< node_t, has_code_location< node_t >::value >::get( node );57 }58 59 template<typename node_t>60 CodeLocation * get_code_location( node_t * node ) {61 return __GetCL< node_t, has_code_location< node_t >::value >::get( node );62 }63 64 26 // Fill every location with a nearby (parent) location. 65 27 class FillCore : public ast::WithGuards { 66 28 CodeLocation const * parent; 29 30 template<typename node_t> 31 node_t const * parse_visit( node_t const * node ) { 32 if ( node->location.isUnset() ) { 33 assert( parent ); 34 node_t * newNode = ast::mutate( node ); 35 newNode->location = *parent; 36 return newNode; 37 } 38 GuardValue( parent ) = &node->location; 39 return node; 40 } 41 42 bool hasUnsetLabels( const ast::Stmt * stmt ) { 43 for ( const ast::Label& label : stmt->labels ) { 44 if ( label.location.isUnset() ) { 45 return true; 46 } 47 } 48 return false; 49 } 50 51 template<typename node_t> 52 node_t const * stmt_visit( node_t const * node ) { 53 assert( node->location.isSet() ); 54 55 if ( hasUnsetLabels( node ) ) { 56 node_t * newNode = ast::mutate( node ); 57 for ( ast::Label& label : newNode->labels ) { 58 if ( label.location.isUnset() ) { 59 label.location = newNode->location; 60 } 61 } 62 return newNode; 63 } 64 return node; 65 } 66 67 template<typename node_t> 68 auto visit( node_t const * node, long ) { 69 return node; 70 } 71 72 template<typename node_t> 73 auto visit( node_t const * node, int ) -> typename 74 std::remove_reference< decltype( node->location, node ) >::type { 75 return parse_visit( node ); 76 } 77 78 template<typename node_t> 79 auto visit( node_t const * node, char ) -> typename 80 std::remove_reference< decltype( node->labels, node ) >::type { 81 return stmt_visit( parse_visit( node ) ); 82 } 83 67 84 public: 68 85 FillCore() : parent( nullptr ) {} 86 FillCore( const CodeLocation& location ) : parent( &location ) { 87 assert( location.isSet() ); 88 } 69 89 70 90 template<typename node_t> 71 91 node_t const * previsit( node_t const * node ) { 72 GuardValue( parent ); 73 CodeLocation const * location = get_code_location( node ); 74 if ( location && location->isUnset() ) { 75 assert( parent ); 76 node_t * newNode = ast::mutate( node ); 77 CodeLocation * newLocation = get_code_location( newNode ); 78 assert( newLocation ); 79 *newLocation = *parent; 80 parent = newLocation; 81 return newNode; 82 } else if ( location ) { 83 parent = location; 84 } 85 return node; 92 return visit( node, '\0' ); 86 93 } 87 94 }; … … 233 240 234 241 template<typename node_t> 235 void previsit( node_t const * node ) { 236 CodeLocation const * location = get_code_location( node ); 237 if ( location && location->isUnset() ) { 242 auto previsit( node_t const * node ) -> decltype( node->location, void() ) { 243 if ( node->location.isUnset() ) { 238 244 unset.push_back( node ); 239 }240 }241 };242 243 class LocalFillCore : public ast::WithGuards {244 CodeLocation const * parent;245 public:246 LocalFillCore( CodeLocation const & location ) : parent( &location ) {247 assert( location.isSet() );248 }249 250 template<typename node_t>251 auto previsit( node_t const * node )252 -> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type {253 if ( node->location.isSet() ) {254 GuardValue( parent ) = &node->location;255 return node;256 } else {257 node_t * mut = ast::mutate( node );258 mut->location = *parent;259 return mut;260 245 } 261 246 } … … 304 289 ast::Node const * localFillCodeLocations( 305 290 CodeLocation const & location , ast::Node const * node ) { 306 ast::Pass< LocalFillCore> visitor( location );291 ast::Pass<FillCore> visitor( location ); 307 292 return node->accept( visitor ); 308 293 } -
src/ControlStruct/LabelGeneratorNew.hpp
rf75e25b re5628db 18 18 #include <string> // for string 19 19 20 classCodeLocation;20 struct CodeLocation; 21 21 22 22 namespace ast { -
src/ControlStruct/MultiLevelExit.cpp
rf75e25b re5628db 18 18 #include "AST/Pass.hpp" 19 19 #include "AST/Stmt.hpp" 20 #include "Common/CodeLocationTools.hpp" 20 21 #include "LabelGeneratorNew.hpp" 21 22 … … 228 229 // Labels on different stmts require different approaches to access 229 230 switch ( stmt->kind ) { 230 231 case BranchStmt::Goto: 231 232 return stmt; 232 233 234 235 236 237 238 239 240 233 case BranchStmt::Continue: 234 case BranchStmt::Break: { 235 bool isContinue = stmt->kind == BranchStmt::Continue; 236 // Handle unlabeled break and continue. 237 if ( stmt->target.empty() ) { 238 if ( isContinue ) { 239 targetEntry = findEnclosingControlStructure( isContinueTarget ); 240 } else { 241 if ( enclosing_control_structures.empty() ) { 241 242 SemanticError( stmt->location, 242 243 "'break' outside a loop, 'switch', or labelled block" ); 243 244 245 246 247 248 249 250 244 } 245 targetEntry = findEnclosingControlStructure( isBreakTarget ); 246 } 247 // Handle labeled break and continue. 248 } else { 249 // Lookup label in table to find attached control structure. 250 targetEntry = findEnclosingControlStructure( 251 [ targetStmt = target_table.at(stmt->target) ](auto entry){ 251 252 return entry.stmt == targetStmt; 252 253 254 255 256 253 } ); 254 } 255 // Ensure that selected target is valid. 256 if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) { 257 SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"), 257 258 " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), 258 259 stmt->originalTarget ) ); 259 260 261 262 263 264 265 266 267 268 269 270 271 272 260 } 261 break; 262 } 263 // handle fallthrough in case/switch stmts 264 case BranchStmt::FallThrough: { 265 targetEntry = findEnclosingControlStructure( isFallthroughTarget ); 266 // Check that target is valid. 267 if ( targetEntry == enclosing_control_structures.rend() ) { 268 SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" ); 269 } 270 if ( ! stmt->target.empty() ) { 271 // Labelled fallthrough: target must be a valid fallthough label. 272 if ( ! fallthrough_labels.count( stmt->target ) ) { 273 SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ", 273 274 stmt->originalTarget ) ); 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 275 } 276 return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget ); 277 } 278 break; 279 } 280 case BranchStmt::FallThroughDefault: { 281 targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget ); 282 283 // Check if in switch or choose statement. 284 if ( targetEntry == enclosing_control_structures.rend() ) { 285 SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" ); 286 } 287 288 // Check if switch or choose has default clause. 289 auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt ); 290 bool foundDefault = false; 291 for ( auto caseStmt : switchStmt->cases ) { 292 if ( caseStmt->isDefault() ) { 293 foundDefault = true; 294 break; 295 } 296 } 297 if ( ! foundDefault ) { 298 SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'" 299 "control structure with a 'default' clause" ); 300 } 301 break; 302 } 303 default: 303 304 assert( false ); 304 305 } … … 307 308 Label exitLabel( CodeLocation(), "" ); 308 309 switch ( stmt->kind ) { 309 310 case BranchStmt::Break: 310 311 assert( ! targetEntry->useBreakExit().empty() ); 311 312 exitLabel = targetEntry->useBreakExit(); 312 313 break; 313 314 case BranchStmt::Continue: 314 315 assert( ! targetEntry->useContExit().empty() ); 315 316 exitLabel = targetEntry->useContExit(); 316 317 break; 317 318 case BranchStmt::FallThrough: 318 319 assert( ! targetEntry->useFallExit().empty() ); 319 320 exitLabel = targetEntry->useFallExit(); 320 321 break; 321 322 case BranchStmt::FallThroughDefault: 322 323 assert( ! targetEntry->useFallDefaultExit().empty() ); 323 324 exitLabel = targetEntry->useFallDefaultExit(); … … 327 328 } 328 329 break; 329 330 default: 330 331 assert(0); 331 332 } … … 633 634 Pass<MultiLevelExitCore> visitor( labelTable ); 634 635 const CompoundStmt * ret = stmt->accept( visitor ); 635 return ret; 636 // There are some unset code locations slipping in, possibly by Labels. 637 const Node * node = localFillCodeLocations( ret->location, ret ); 638 return strict_dynamic_cast<const CompoundStmt *>( node ); 636 639 } 637 640 } // namespace ControlStruct -
src/Parser/parser.yy
rf75e25b re5628db 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 4 1 4:25:20202213 // Update Count : 527 712 // Last Modified On : Wed May 4 17:22:48 2022 13 // Update Count : 5279 14 14 // 15 15 … … 1224 1224 { $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); } 1225 1225 | WHILE '(' ')' statement ELSE statement // CFA 1226 { $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); SemanticWarning( yylloc, Warning::SuperfluousElse ); } 1226 { 1227 $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); 1228 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1229 } 1227 1230 | WHILE '(' conditional_declaration ')' statement %prec THEN 1228 1231 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); } … … 1232 1235 { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); } 1233 1236 | DO statement WHILE '(' ')' ELSE statement // CFA 1234 { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); SemanticWarning( yylloc, Warning::SuperfluousElse ); } 1235 | DO statement WHILE '(' comma_expression ')' ';' %prec THEN 1237 { 1238 $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); 1239 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1240 } 1241 | DO statement WHILE '(' comma_expression ')' ';' 1236 1242 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); } 1237 1243 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA 1238 1244 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); } 1239 | FOR '(' ')' statement // CFA => for ( ;; )1245 | FOR '(' ')' statement %prec THEN // CFA => for ( ;; ) 1240 1246 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); } 1241 | FOR '(' ')' statement ELSE statement // CFA 1242 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); SemanticWarning( yylloc, Warning::SuperfluousElse ); } 1247 | FOR '(' ')' statement ELSE statement // CFA 1248 { 1249 $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); 1250 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1251 } 1243 1252 | FOR '(' for_control_expression_list ')' statement %prec THEN 1244 1253 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); } -
src/Validate/Autogen.cpp
rf75e25b re5628db 350 350 name, 351 351 std::move( type_params ), 352 std::move( assertions ), 352 353 std::move( params ), 353 354 std::move( returns ), … … 360 361 // Auto-generated routines are inline to avoid conflicts. 361 362 ast::Function::Specs( ast::Function::Inline ) ); 362 decl->assertions = std::move( assertions );363 363 decl->fixUniqueId(); 364 364 return decl; -
tests/include/.expect/includes.nast.txt
rf75e25b re5628db 1 include/includes.cfa:1 53:25: warning: Compiled1 include/includes.cfa:169:25: warning: Compiled -
tests/include/includes.cfa
rf75e25b re5628db 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : T hu Feb 3 22:06:07202213 // Update Count : 77 412 // Last Modified On : Tue May 10 16:36:44 2022 13 // Update Count : 776 14 14 // 15 15 … … 32 32 #include <crypt.h> 33 33 #include <ctype.h> 34 //#include <curses.h> // may not be installed 34 #if __has_include( "curses.h" ) 35 #include <curses.h> // may not be installed 36 #endif 35 37 #include <dirent.h> 36 38 #include <dlfcn.h> … … 41 43 #include <errno.h> 42 44 #include <error.h> 43 //#include <eti.h> // may not be installed, comes with ncurses 45 #if __has_include( "eti.h" ) 46 #include <eti.h> // may not be installed, comes with ncurses 47 #endif 44 48 #include <execinfo.h> 45 49 #include <expat.h> … … 50 54 #include <fmtmsg.h> 51 55 #include <fnmatch.h> 52 //#include <form.h> // may not be installed, comes with ncurses 56 #if __has_include( "form.h" ) 57 #include <form.h> // may not be installed, comes with ncurses 58 #endif 53 59 #include <fstab.h> 54 60 #include <fts.h> … … 78 84 #include <mcheck.h> 79 85 #include <memory.h> 80 //#include <menu.h> // may not be installed, comes with ncurses 86 #if __has_include( "menu.h" ) 87 #include <menu.h> // may not be installed, comes with ncurses 88 #endif 81 89 #include <mntent.h> 82 90 #include <monetary.h> 83 91 #include <mqueue.h> 84 //#include <ncurses_dll.h> // may not be installed, comes with ncurses 92 #if __has_include( "ncurses_dll.h" ) 93 #include <ncurses_dll.h> // may not be installed, comes with ncurses 94 #endif 85 95 #include <netdb.h> 86 96 #include <nl_types.h> 87 97 #include <nss.h> 88 98 #include <obstack.h> 89 //#include <panel.h> // may not be installed, comes with ncurses 99 #if __has_include( "panel.h" ) 100 #include <panel.h> // may not be installed, comes with ncurses 101 #endif 90 102 #include <paths.h> 91 103 #include <poll.h> … … 118 130 #include <syslog.h> 119 131 #include <tar.h> 120 //#include <term.h> // may not be installed, comes with ncurses 121 //#include <termcap.h> // may not be installed, comes with ncurses 132 #if __has_include( "term.h" ) 133 #include <term.h> // may not be installed, comes with ncurses 134 #include <termcap.h> // may not be installed, comes with ncurses 135 #endif 122 136 #include <termio.h> 123 137 #include <termios.h> … … 131 145 #include <ucontext.h> 132 146 #include <ulimit.h> 133 //#include <unctrl.h> // may not be installed, comes with ncurses 147 #if __has_include( "unctrl.h" ) 148 #include <unctrl.h> // may not be installed, comes with ncurses 149 #endif 134 150 #include <unistd.h> 135 151 #include <utime.h>
Note: See TracChangeset
for help on using the changeset viewer.