Changes in / [656ee4f:626da644]
- Files:
-
- 6 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Concurrency/Keywords.cc
r656ee4f r626da644 17 17 #include "Concurrency/Keywords.h" 18 18 19 #include "InitTweak/InitTweak.h" 19 20 #include "SymTab/AddVisit.h" 20 21 #include "SynTree/Declaration.h" 21 22 #include "SynTree/Expression.h" 22 23 #include "SynTree/Initializer.h" 23 #include "SynTree/Mutator.h"24 24 #include "SynTree/Statement.h" 25 25 #include "SynTree/Type.h" … … 38 38 // Visitors declaration 39 39 //============================================================================================= 40 41 //----------------------------------------------------------------------------- 42 //Handles sue type declarations : 43 // sue MyType { struct MyType { 44 // int data; int data; 45 // a_struct_t more_data; a_struct_t more_data; 46 // => NewField_t newField; 47 // }; }; 48 // static inline NewField_t * getter_name( MyType * this ) { return &this->newField; } 49 // 50 class ConcurrentSueKeyword : public Visitor { 51 protected: 52 template< typename Visitor > 53 friend void SymTab::acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor ); 54 public: 55 56 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main ) : 57 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ) {} 58 59 virtual ~ConcurrentSueKeyword() {} 60 61 using Visitor::visit; 62 virtual void visit( StructDecl * decl ) override final; 63 64 void handle( StructDecl * ); 65 FunctionDecl * forwardDeclare( StructDecl * ); 66 ObjectDecl * addField( StructDecl * ); 67 void addRoutines( StructDecl *, ObjectDecl *, FunctionDecl * ); 68 69 virtual bool is_target( StructDecl * decl ) = 0; 70 71 private: 72 const std::string type_name; 73 const std::string field_name; 74 const std::string getter_name; 75 const std::string context_error; 76 bool needs_main; 77 78 std::list< Declaration * > declsToAdd, declsToAddAfter; 79 StructDecl* type_decl = nullptr; 80 }; 81 40 82 41 83 //----------------------------------------------------------------------------- … … 47 89 // }; }; 48 90 // static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; } 49 // void main( MyThread * this );50 91 // 51 class ThreadKeyword final : public Mutator{92 class ThreadKeyword final : public ConcurrentSueKeyword { 52 93 public: 53 94 54 static void implement( std::list< Declaration * > & translationUnit ) {} 95 ThreadKeyword() : ConcurrentSueKeyword( 96 "thread_desc", 97 "__thrd", 98 "get_thread", 99 "thread keyword requires threads to be in scope, add #include <thread>", 100 true 101 ) 102 {} 103 104 virtual ~ThreadKeyword() {} 105 106 virtual bool is_target( StructDecl * decl ) override final { return decl->is_thread(); } 107 108 static void implement( std::list< Declaration * > & translationUnit ) { 109 ThreadKeyword impl; 110 SymTab::acceptAndAdd( translationUnit, impl ); 111 } 55 112 }; 56 113 … … 63 120 // }; }; 64 121 // static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; } 65 // void main( MyCoroutine * this );66 122 // 67 class CoroutineKeyword final : public Visitor { 68 template< typename Visitor > 69 friend void SymTab::acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor ); 123 class CoroutineKeyword final : public ConcurrentSueKeyword { 70 124 public: 71 125 72 using Visitor::visit; 73 virtual void visit( StructDecl * decl ) override final; 74 75 void handle( StructDecl * ); 76 Declaration * addField( StructDecl * ); 77 void addRoutines( StructDecl *, Declaration * ); 126 CoroutineKeyword() : ConcurrentSueKeyword( 127 "coroutine_desc", 128 "__cor", 129 "get_coroutine", 130 "coroutine keyword requires coroutines to be in scope, add #include <coroutine>", 131 true 132 ) 133 {} 134 135 virtual ~CoroutineKeyword() {} 136 137 virtual bool is_target( StructDecl * decl ) override final { return decl->is_coroutine(); } 78 138 79 139 static void implement( std::list< Declaration * > & translationUnit ) { … … 81 141 SymTab::acceptAndAdd( translationUnit, impl ); 82 142 } 83 84 private:85 std::list< Declaration * > declsToAdd, declsToAddAfter;86 StructDecl* coroutine_decl = nullptr;87 143 }; 88 144 … … 95 151 // }; }; 96 152 // static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; } 97 // void main( MyMonitor * this );98 153 // 99 class MonitorKeyword final : public Mutator{154 class MonitorKeyword final : public ConcurrentSueKeyword { 100 155 public: 101 156 102 static void implement( std::list< Declaration * > & translationUnit ) {} 157 MonitorKeyword() : ConcurrentSueKeyword( 158 "monitor_desc", 159 "__mon", 160 "get_monitor", 161 "monitor keyword requires monitors to be in scope, add #include <monitor>", 162 false 163 ) 164 {} 165 166 virtual ~MonitorKeyword() {} 167 168 virtual bool is_target( StructDecl * decl ) override final { return decl->is_monitor(); } 169 170 static void implement( std::list< Declaration * > & translationUnit ) { 171 MonitorKeyword impl; 172 SymTab::acceptAndAdd( translationUnit, impl ); 173 } 103 174 }; 104 175 … … 132 203 }; 133 204 205 //----------------------------------------------------------------------------- 206 //Handles mutex routines definitions : 207 // void foo( A * mutex a, B * mutex b, int i ) { void foo( A * a, B * b, int i ) { 208 // monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) }; 209 // monitor_guard_t __guard = { __monitors, 2 }; 210 // /*Some code*/ => /*Some code*/ 211 // } } 212 // 213 class ThreadStarter final : public Visitor { 214 public: 215 216 using Visitor::visit; 217 virtual void visit( FunctionDecl * decl ) override final; 218 219 void addStartStatement( FunctionDecl * decl, DeclarationWithType * param ); 220 221 static void implement( std::list< Declaration * > & translationUnit ) { 222 ThreadStarter impl; 223 acceptAll( translationUnit, impl ); 224 } 225 }; 226 134 227 //============================================================================================= 135 228 // General entry routine … … 139 232 CoroutineKeyword ::implement( translationUnit ); 140 233 MonitorKeyword ::implement( translationUnit ); 234 } 235 236 void implementMutexFuncs( std::list< Declaration * > & translationUnit ) { 141 237 MutexKeyword ::implement( translationUnit ); 142 238 } 143 239 144 //============================================================================================= 145 // Coroutine keyword implementation 146 //============================================================================================= 147 void CoroutineKeyword::visit(StructDecl * decl) { 148 if( decl->get_name() == "coroutine_desc" ) { 149 assert( !coroutine_decl ); 150 coroutine_decl = decl; 151 } 152 else if ( decl->is_coroutine() ) { 240 void implementThreadStarter( std::list< Declaration * > & translationUnit ) { 241 ThreadStarter ::implement( translationUnit ); 242 } 243 244 //============================================================================================= 245 // Generic keyword implementation 246 //============================================================================================= 247 void ConcurrentSueKeyword::visit(StructDecl * decl) { 248 if( decl->get_name() == type_name ) { 249 assert( !type_decl ); 250 type_decl = decl; 251 } 252 else if ( is_target(decl) ) { 153 253 handle( decl ); 154 254 } … … 156 256 } 157 257 158 void Co routineKeyword::handle( StructDecl * decl ) {258 void ConcurrentSueKeyword::handle( StructDecl * decl ) { 159 259 if( ! decl->has_body() ) return; 160 260 161 if( !coroutine_decl ) throw SemanticError( "coroutine keyword requires coroutines to be in scope, add #include <coroutine>", decl ); 162 163 Declaration * field = addField( decl ); 164 addRoutines( decl, field ); 165 } 166 167 Declaration * CoroutineKeyword::addField( StructDecl * decl ) { 168 Declaration * cor = new ObjectDecl( 169 "__cor", 261 if( !type_decl ) throw SemanticError( context_error, decl ); 262 263 FunctionDecl * func = forwardDeclare( decl ); 264 ObjectDecl * field = addField( decl ); 265 addRoutines( decl, field, func ); 266 } 267 268 FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) { 269 270 StructDecl * forward = decl->clone(); 271 forward->set_body( false ); 272 deleteAll( forward->get_members() ); 273 forward->get_members().clear(); 274 275 FunctionType * get_type = new FunctionType( noQualifiers, false ); 276 ObjectDecl * this_decl = new ObjectDecl( 277 "this", 170 278 noStorage, 171 279 LinkageSpec::Cforall, 172 280 nullptr, 173 new StructInstType(281 new PointerType( 174 282 noQualifiers, 175 coroutine_decl 283 new StructInstType( 284 noQualifiers, 285 decl 286 ) 176 287 ), 177 288 nullptr 178 289 ); 179 290 180 decl->get_members().push_back( cor ); 181 182 return cor; 183 } 184 185 void CoroutineKeyword::addRoutines( StructDecl * decl, Declaration * field ) { 186 FunctionType * type = new FunctionType( noQualifiers, false ); 187 type->get_parameters().push_back( 188 new ObjectDecl( 189 "this", 190 noStorage, 191 LinkageSpec::Cforall, 192 nullptr, 193 new PointerType( 194 noQualifiers, 195 new StructInstType( 196 noQualifiers, 197 decl 198 ) 199 ), 200 nullptr 201 ) 202 ); 203 type->get_returnVals().push_back( 291 get_type->get_parameters().push_back( this_decl ); 292 get_type->get_returnVals().push_back( 204 293 new ObjectDecl( 205 294 "ret", … … 211 300 new StructInstType( 212 301 noQualifiers, 213 coroutine_decl302 type_decl 214 303 ) 215 304 ), … … 218 307 ); 219 308 309 FunctionDecl * get_decl = new FunctionDecl( 310 getter_name, 311 Type::Static, 312 LinkageSpec::Cforall, 313 get_type, 314 nullptr, 315 noAttributes, 316 Type::Inline 317 ); 318 319 FunctionDecl * main_decl = nullptr; 320 321 if( needs_main ) { 322 FunctionType * main_type = new FunctionType( noQualifiers, false ); 323 324 main_type->get_parameters().push_back( this_decl->clone() ); 325 326 main_decl = new FunctionDecl( 327 "main", 328 noStorage, 329 LinkageSpec::Cforall, 330 main_type, 331 nullptr 332 ); 333 } 334 335 declsToAdd.push_back( forward ); 336 if( needs_main ) declsToAdd.push_back( main_decl ); 337 declsToAdd.push_back( get_decl ); 338 339 return get_decl; 340 } 341 342 ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) { 343 ObjectDecl * field = new ObjectDecl( 344 field_name, 345 noStorage, 346 LinkageSpec::Cforall, 347 nullptr, 348 new StructInstType( 349 noQualifiers, 350 type_decl 351 ), 352 nullptr 353 ); 354 355 decl->get_members().push_back( field ); 356 357 return field; 358 } 359 360 void ConcurrentSueKeyword::addRoutines( StructDecl * decl, ObjectDecl * field, FunctionDecl * func ) { 220 361 CompoundStmt * statement = new CompoundStmt( noLabels ); 221 362 statement->push_back( … … 223 364 noLabels, 224 365 new AddressExpr( 225 new UntypedMemberExpr( 226 new NameExpr( "__cor" ), 227 new UntypedExpr( 228 new NameExpr( "*?" ), 229 { new NameExpr( "this" ) } 230 ) 366 new MemberExpr( 367 field, 368 UntypedExpr::createDeref( new VariableExpr( func->get_functionType()->get_parameters().front() ) ) 231 369 ) 232 370 ) … … 234 372 ); 235 373 236 FunctionDecl * get_decl = new FunctionDecl( 237 "get_coroutine", 238 Type::Static, 239 LinkageSpec::Cforall, 240 type, 241 statement, 242 noAttributes, 243 Type::Inline 244 ); 374 FunctionDecl * get_decl = func->clone(); 375 376 get_decl->set_statements( statement ); 245 377 246 378 declsToAddAfter.push_back( get_decl ); 247 379 248 get_decl->fixUniqueId(); 249 } 250 380 // get_decl->fixUniqueId(); 381 } 251 382 252 383 //============================================================================================= … … 368 499 body->push_front( new DeclStmt( noLabels, monitors) ); 369 500 } 501 502 //============================================================================================= 503 // General entry routine 504 //============================================================================================= 505 void ThreadStarter::visit(FunctionDecl * decl) { 506 if( ! InitTweak::isConstructor(decl->get_name()) ) return; 507 508 DeclarationWithType * param = decl->get_functionType()->get_parameters().front(); 509 auto ptr = dynamic_cast< PointerType * >( param->get_type() ); 510 // if( ptr ) std::cerr << "FRED1" << std::endl; 511 auto type = dynamic_cast< StructInstType * >( ptr->get_base() ); 512 // if( type ) std::cerr << "FRED2" << std::endl; 513 if( type && type->get_baseStruct()->is_thread() ) { 514 addStartStatement( decl, param ); 515 } 516 } 517 518 void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) { 519 CompoundStmt * stmt = decl->get_statements(); 520 521 if( ! stmt ) return; 522 523 stmt->push_back( 524 new ExprStmt( 525 noLabels, 526 new UntypedExpr( 527 new NameExpr( "__thrd_start" ), 528 { new VariableExpr( param ) } 529 ) 530 ) 531 ); 532 } 370 533 }; -
src/Concurrency/Keywords.h
r656ee4f r626da644 24 24 namespace Concurrency { 25 25 void applyKeywords( std::list< Declaration * > & translationUnit ); 26 void implementMutexFuncs( std::list< Declaration * > & translationUnit ); 27 void implementThreadStarter( std::list< Declaration * > & translationUnit ); 26 28 }; 27 29 -
src/Parser/lex.ll
r656ee4f r626da644 236 236 long { KEYWORD_RETURN(LONG); } 237 237 lvalue { KEYWORD_RETURN(LVALUE); } // CFA 238 _Monitor { KEYWORD_RETURN(MONITOR); } // CFA238 monitor { KEYWORD_RETURN(MONITOR); } // CFA 239 239 mutex { KEYWORD_RETURN(MUTEX); } // CFA 240 240 _Noreturn { KEYWORD_RETURN(NORETURN); } // C11 … … 256 256 struct { KEYWORD_RETURN(STRUCT); } 257 257 switch { KEYWORD_RETURN(SWITCH); } 258 _Thread { KEYWORD_RETURN(THREAD); } // C11258 thread { KEYWORD_RETURN(THREAD); } // C11 259 259 _Thread_local { KEYWORD_RETURN(THREADLOCAL); } // C11 260 260 throw { KEYWORD_RETURN(THROW); } // CFA -
src/SymTab/Autogen.cc
r656ee4f r626da644 218 218 219 219 /// generates a function (?{}, ?=?, ^?{}) based on the data argument and members. If function is generated, inserts the type into the map. 220 void gen( const FuncData & data ) {220 void gen( const FuncData & data, bool concurrent_type ) { 221 221 if ( ! shouldGenerate( data.map, aggregateDecl ) ) return; 222 222 FunctionType * ftype = data.genType( refType ); 223 224 if(concurrent_type && InitTweak::isDestructor( data.fname )) { 225 ftype->get_parameters().front()->get_type()->set_mutex( true ); 226 } 227 223 228 cloneAll( typeParams, ftype->get_forall() ); 224 229 *out++ = genFunc( data.fname, ftype, functionNesting ); … … 403 408 auto generator = makeFuncGenerator( aggregateDecl, refType, functionNesting, typeParams, back_inserter( newFuncs ) ); 404 409 for ( const FuncData & d : data ) { 405 generator.gen( d ); 406 } 410 generator.gen( d, aggregateDecl->is_thread() || aggregateDecl->is_monitor() ); 411 } 412 407 413 // field ctors are only generated if default constructor and copy constructor are both generated 408 414 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } ); -
src/SymTab/Validate.cc
r656ee4f r626da644 43 43 #include "Common/utility.h" 44 44 #include "Common/UniqueName.h" 45 #include "Concurrency/Keywords.h" 45 46 #include "Validate.h" 46 47 #include "SynTree/Visitor.h" … … 225 226 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen 226 227 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions 228 Concurrency::applyKeywords( translationUnit ); 227 229 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass 230 Concurrency::implementMutexFuncs( translationUnit ); 231 Concurrency::implementThreadStarter( translationUnit ); 228 232 acceptAll( translationUnit, epc ); 229 233 ReturnChecker::checkFunctionReturns( translationUnit ); -
src/libcfa/concurrency/thread
r656ee4f r626da644 56 56 thread_desc * this_thread(void); 57 57 58 forall( dtype T | is_thread(T) ) 59 void __thrd_start( T* this ); 60 58 61 //----------------------------------------------------------------------------- 59 62 // Ctors and dtors -
src/libcfa/concurrency/thread.c
r656ee4f r626da644 31 31 32 32 //----------------------------------------------------------------------------- 33 // Forward declarations34 forall( dtype T | is_thread(T) )35 void start( T* this );36 37 //-----------------------------------------------------------------------------38 33 // Thread ctors and dtors 39 34 … … 53 48 void ?{}( scoped(T)* this ) { 54 49 (&this->handle){}; 55 start(&this->handle);50 __thrd_start(&this->handle); 56 51 } 57 52 … … 59 54 void ?{}( scoped(T)* this, P params ) { 60 55 (&this->handle){ params }; 61 start(&this->handle);56 __thrd_start(&this->handle); 62 57 } 63 58 … … 70 65 // Starting and stopping threads 71 66 forall( dtype T | is_thread(T) ) 72 void start( T* this ) {67 void __thrd_start( T* this ) { 73 68 coroutine_desc* thrd_c = get_coroutine(this); 74 69 thread_desc* thrd_h = get_thread (this); -
src/main.cc
r656ee4f r626da644 216 216 } // if 217 217 218 // OPTPRINT( "Concurrency" ) 219 // Concurrency::applyKeywords( translationUnit ); 220 218 221 // add the assignment statement after the initialization of a type parameter 219 222 OPTPRINT( "validate" ) … … 237 240 OPTPRINT( "mutate" ) 238 241 ControlStruct::mutate( translationUnit ); 239 OPTPRINT( "Concurrency" )240 Concurrency::applyKeywords( translationUnit );241 242 OPTPRINT( "fixNames" ) 242 243 CodeGen::fixNames( translationUnit ); -
src/tests/monitor.c
r656ee4f r626da644 4 4 #include <thread> 5 5 6 structglobal_t {6 monitor global_t { 7 7 int value; 8 monitor_desc m;9 8 }; 10 9 11 10 void ?{}(global_t * this) { 12 11 this->value = 0; 13 }14 15 monitor_desc * get_monitor( global_t * this ) {16 return &this->m;17 12 } 18 13 … … 31 26 } 32 27 33 struct MyThread { thread_desc __thrd; }; 34 35 DECL_THREAD(MyThread); 36 37 void ?{}( MyThread * this ) {} 38 void ^?{}( MyThread * mutex this ) {} 28 thread MyThread {}; 39 29 40 30 void main( MyThread* this ) { … … 45 35 46 36 int main(int argc, char* argv[]) { 47 assert( global. m.entry_queue.tail != NULL );37 assert( global.__mon.entry_queue.tail != NULL ); 48 38 processor p; 49 39 { 50 scoped(MyThread)f[4];40 MyThread f[4]; 51 41 } 52 42 sout | global.value | endl; -
src/tests/multi-monitor.c
r656ee4f r626da644 6 6 static int global12, global23, global13; 7 7 8 struct monitor_t { 9 monitor_desc m; 10 }; 11 12 monitor_desc * get_monitor( monitor_t * this ) { 13 return &this->m; 14 } 8 monitor monitor_t {}; 15 9 16 10 static monitor_t m1, m2, m3; -
src/tests/thread.c
r656ee4f r626da644 4 4 #include <thread> 5 5 6 struct First { thread_desc __thrd; signal_once* lock; };7 struct Second { thread_desc __thrd; signal_once* lock; };6 // thread First; 7 // void main(First* this); 8 8 9 DECL_THREAD(First); 10 DECL_THREAD(Second); 9 // thread Second; 10 // void main(Second* this); 11 12 thread First { signal_once* lock; }; 13 thread Second { signal_once* lock; }; 11 14 12 15 void ?{}( First * this, signal_once* lock ) { this->lock = lock; } 13 16 void ?{}( Second * this, signal_once* lock ) { this->lock = lock; } 14 15 void ^?{}( First * mutex this ) {}16 void ^?{}( Second * mutex this ) {}17 17 18 18 void main(First* this) { … … 39 39 processor p; 40 40 { 41 scoped(First)f = { &lock };42 scoped(Second)s = { &lock };41 First f = { &lock }; 42 Second s = { &lock }; 43 43 } 44 44 }
Note:
See TracChangeset
for help on using the changeset viewer.