| [64adb03] | 1 | //                              -*- Mode: CPP -*- | 
|---|
|  | 2 | // | 
|---|
|  | 3 | // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo | 
|---|
|  | 4 | // | 
|---|
|  | 5 | // The contents of this file are covered under the licence agreement in the | 
|---|
|  | 6 | // file "LICENCE" distributed with Cforall. | 
|---|
|  | 7 | // | 
|---|
|  | 8 | // Keywords.cc -- | 
|---|
|  | 9 | // | 
|---|
|  | 10 | // Author           : Thierry Delisle | 
|---|
|  | 11 | // Created On       : Mon Mar 13 12:41:22 2017 | 
|---|
|  | 12 | // Last Modified By : | 
|---|
|  | 13 | // Last Modified On : | 
|---|
| [615a096] | 14 | // Update Count     : 3 | 
|---|
| [64adb03] | 15 | // | 
|---|
|  | 16 |  | 
|---|
|  | 17 | #include "Concurrency/Keywords.h" | 
|---|
|  | 18 |  | 
|---|
| [bd4d011] | 19 | #include "InitTweak/InitTweak.h" | 
|---|
| [b32ada31] | 20 | #include "SymTab/AddVisit.h" | 
|---|
| [64adb03] | 21 | #include "SynTree/Declaration.h" | 
|---|
|  | 22 | #include "SynTree/Expression.h" | 
|---|
|  | 23 | #include "SynTree/Initializer.h" | 
|---|
|  | 24 | #include "SynTree/Statement.h" | 
|---|
|  | 25 | #include "SynTree/Type.h" | 
|---|
|  | 26 | #include "SynTree/Visitor.h" | 
|---|
|  | 27 |  | 
|---|
|  | 28 | namespace Concurrency { | 
|---|
|  | 29 |  | 
|---|
|  | 30 | namespace { | 
|---|
|  | 31 | const std::list<Label> noLabels; | 
|---|
| [b32ada31] | 32 | const std::list< Attribute * > noAttributes; | 
|---|
| [68fe077a] | 33 | Type::StorageClasses noStorage; | 
|---|
| [64adb03] | 34 | Type::Qualifiers noQualifiers; | 
|---|
|  | 35 | } | 
|---|
|  | 36 |  | 
|---|
|  | 37 | //============================================================================================= | 
|---|
|  | 38 | // Visitors declaration | 
|---|
|  | 39 | //============================================================================================= | 
|---|
|  | 40 |  | 
|---|
| [bcda04c] | 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 |  | 
|---|
| [bd4d011] | 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 ) {} | 
|---|
| [bcda04c] | 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 * ); | 
|---|
| [2f9a722] | 67 | void addRoutines( ObjectDecl *, FunctionDecl * ); | 
|---|
| [bcda04c] | 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; | 
|---|
| [bd4d011] | 76 | bool needs_main; | 
|---|
| [bcda04c] | 77 |  | 
|---|
|  | 78 | std::list< Declaration * > declsToAdd, declsToAddAfter; | 
|---|
|  | 79 | StructDecl* type_decl = nullptr; | 
|---|
|  | 80 | }; | 
|---|
|  | 81 |  | 
|---|
|  | 82 |  | 
|---|
| [64adb03] | 83 | //----------------------------------------------------------------------------- | 
|---|
|  | 84 | //Handles thread type declarations : | 
|---|
|  | 85 | // thread Mythread {                         struct MyThread { | 
|---|
|  | 86 | //      int data;                                  int data; | 
|---|
|  | 87 | //      a_struct_t more_data;                      a_struct_t more_data; | 
|---|
|  | 88 | //                                =>             thread_desc __thrd_d; | 
|---|
|  | 89 | // };                                        }; | 
|---|
|  | 90 | //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; } | 
|---|
|  | 91 | // | 
|---|
| [bcda04c] | 92 | class ThreadKeyword final : public ConcurrentSueKeyword { | 
|---|
| [64adb03] | 93 | public: | 
|---|
|  | 94 |  | 
|---|
| [bcda04c] | 95 | ThreadKeyword() : ConcurrentSueKeyword( | 
|---|
|  | 96 | "thread_desc", | 
|---|
|  | 97 | "__thrd", | 
|---|
|  | 98 | "get_thread", | 
|---|
| [bd4d011] | 99 | "thread keyword requires threads to be in scope, add #include <thread>", | 
|---|
|  | 100 | true | 
|---|
| [bcda04c] | 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 | } | 
|---|
| [64adb03] | 112 | }; | 
|---|
|  | 113 |  | 
|---|
|  | 114 | //----------------------------------------------------------------------------- | 
|---|
|  | 115 | //Handles coroutine type declarations : | 
|---|
|  | 116 | // coroutine MyCoroutine {                   struct MyCoroutine { | 
|---|
|  | 117 | //      int data;                                  int data; | 
|---|
|  | 118 | //      a_struct_t more_data;                      a_struct_t more_data; | 
|---|
|  | 119 | //                                =>             coroutine_desc __cor_d; | 
|---|
|  | 120 | // };                                        }; | 
|---|
|  | 121 | //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; } | 
|---|
|  | 122 | // | 
|---|
| [bcda04c] | 123 | class CoroutineKeyword final : public ConcurrentSueKeyword { | 
|---|
| [64adb03] | 124 | public: | 
|---|
|  | 125 |  | 
|---|
| [bcda04c] | 126 | CoroutineKeyword() : ConcurrentSueKeyword( | 
|---|
|  | 127 | "coroutine_desc", | 
|---|
|  | 128 | "__cor", | 
|---|
|  | 129 | "get_coroutine", | 
|---|
| [bd4d011] | 130 | "coroutine keyword requires coroutines to be in scope, add #include <coroutine>", | 
|---|
|  | 131 | true | 
|---|
| [bcda04c] | 132 | ) | 
|---|
|  | 133 | {} | 
|---|
| [b32ada31] | 134 |  | 
|---|
| [bcda04c] | 135 | virtual ~CoroutineKeyword() {} | 
|---|
|  | 136 |  | 
|---|
|  | 137 | virtual bool is_target( StructDecl * decl ) override final { return decl->is_coroutine(); } | 
|---|
| [b32ada31] | 138 |  | 
|---|
|  | 139 | static void implement( std::list< Declaration * > & translationUnit ) { | 
|---|
|  | 140 | CoroutineKeyword impl; | 
|---|
|  | 141 | SymTab::acceptAndAdd( translationUnit, impl ); | 
|---|
|  | 142 | } | 
|---|
| [64adb03] | 143 | }; | 
|---|
|  | 144 |  | 
|---|
|  | 145 | //----------------------------------------------------------------------------- | 
|---|
|  | 146 | //Handles monitor type declarations : | 
|---|
|  | 147 | // monitor MyMonitor {                       struct MyMonitor { | 
|---|
|  | 148 | //      int data;                                  int data; | 
|---|
|  | 149 | //      a_struct_t more_data;                      a_struct_t more_data; | 
|---|
|  | 150 | //                                =>             monitor_desc __mon_d; | 
|---|
|  | 151 | // };                                        }; | 
|---|
|  | 152 | //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; } | 
|---|
|  | 153 | // | 
|---|
| [bcda04c] | 154 | class MonitorKeyword final : public ConcurrentSueKeyword { | 
|---|
| [64adb03] | 155 | public: | 
|---|
|  | 156 |  | 
|---|
| [bcda04c] | 157 | MonitorKeyword() : ConcurrentSueKeyword( | 
|---|
|  | 158 | "monitor_desc", | 
|---|
|  | 159 | "__mon", | 
|---|
|  | 160 | "get_monitor", | 
|---|
| [bd4d011] | 161 | "monitor keyword requires monitors to be in scope, add #include <monitor>", | 
|---|
|  | 162 | false | 
|---|
| [bcda04c] | 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 | } | 
|---|
| [64adb03] | 174 | }; | 
|---|
|  | 175 |  | 
|---|
|  | 176 | //----------------------------------------------------------------------------- | 
|---|
|  | 177 | //Handles mutex routines definitions : | 
|---|
|  | 178 | // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) { | 
|---|
| [9243cc91] | 179 | //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) }; | 
|---|
| [64adb03] | 180 | //                                                                       monitor_guard_t __guard = { __monitors, 2 }; | 
|---|
|  | 181 | //    /*Some code*/                                       =>           /*Some code*/ | 
|---|
|  | 182 | // }                                                               } | 
|---|
|  | 183 | // | 
|---|
|  | 184 | class MutexKeyword final : public Visitor { | 
|---|
|  | 185 | public: | 
|---|
|  | 186 |  | 
|---|
|  | 187 | using Visitor::visit; | 
|---|
| [b32ada31] | 188 | virtual void visit( FunctionDecl * decl ) override final; | 
|---|
|  | 189 | virtual void visit(   StructDecl * decl ) override final; | 
|---|
| [64adb03] | 190 |  | 
|---|
|  | 191 | std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* ); | 
|---|
|  | 192 | void validate( DeclarationWithType * ); | 
|---|
|  | 193 | void addStatments( CompoundStmt *, const std::list<DeclarationWithType * > &); | 
|---|
|  | 194 |  | 
|---|
|  | 195 | static void implement( std::list< Declaration * > & translationUnit ) { | 
|---|
|  | 196 | MutexKeyword impl; | 
|---|
|  | 197 | acceptAll( translationUnit, impl ); | 
|---|
|  | 198 | } | 
|---|
| [9243cc91] | 199 |  | 
|---|
|  | 200 | private: | 
|---|
|  | 201 | StructDecl* monitor_decl = nullptr; | 
|---|
| [ef42b143] | 202 | StructDecl* guard_decl = nullptr; | 
|---|
| [64adb03] | 203 | }; | 
|---|
|  | 204 |  | 
|---|
| [bd4d011] | 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 |  | 
|---|
| [64adb03] | 227 | //============================================================================================= | 
|---|
|  | 228 | // General entry routine | 
|---|
|  | 229 | //============================================================================================= | 
|---|
|  | 230 | void applyKeywords( std::list< Declaration * > & translationUnit ) { | 
|---|
|  | 231 | ThreadKeyword   ::implement( translationUnit ); | 
|---|
|  | 232 | CoroutineKeyword        ::implement( translationUnit ); | 
|---|
|  | 233 | MonitorKeyword  ::implement( translationUnit ); | 
|---|
| [bcda04c] | 234 | } | 
|---|
|  | 235 |  | 
|---|
|  | 236 | void implementMutexFuncs( std::list< Declaration * > & translationUnit ) { | 
|---|
| [64adb03] | 237 | MutexKeyword    ::implement( translationUnit ); | 
|---|
|  | 238 | } | 
|---|
|  | 239 |  | 
|---|
| [bcda04c] | 240 | void implementThreadStarter( std::list< Declaration * > & translationUnit ) { | 
|---|
| [bd4d011] | 241 | ThreadStarter   ::implement( translationUnit ); | 
|---|
| [bcda04c] | 242 | } | 
|---|
|  | 243 |  | 
|---|
| [b32ada31] | 244 | //============================================================================================= | 
|---|
| [bcda04c] | 245 | // Generic keyword implementation | 
|---|
| [b32ada31] | 246 | //============================================================================================= | 
|---|
| [bcda04c] | 247 | void ConcurrentSueKeyword::visit(StructDecl * decl) { | 
|---|
| [102a58b] | 248 | Visitor::visit(decl); | 
|---|
| [2f9a722] | 249 | if( decl->get_name() == type_name && decl->has_body() ) { | 
|---|
| [bcda04c] | 250 | assert( !type_decl ); | 
|---|
|  | 251 | type_decl = decl; | 
|---|
| [b32ada31] | 252 | } | 
|---|
| [bcda04c] | 253 | else if ( is_target(decl) ) { | 
|---|
| [b32ada31] | 254 | handle( decl ); | 
|---|
|  | 255 | } | 
|---|
|  | 256 |  | 
|---|
|  | 257 | } | 
|---|
|  | 258 |  | 
|---|
| [bcda04c] | 259 | void ConcurrentSueKeyword::handle( StructDecl * decl ) { | 
|---|
| [b32ada31] | 260 | if( ! decl->has_body() ) return; | 
|---|
|  | 261 |  | 
|---|
| [bcda04c] | 262 | if( !type_decl ) throw SemanticError( context_error, decl ); | 
|---|
| [b32ada31] | 263 |  | 
|---|
| [bcda04c] | 264 | FunctionDecl * func = forwardDeclare( decl ); | 
|---|
|  | 265 | ObjectDecl * field = addField( decl ); | 
|---|
| [2f9a722] | 266 | addRoutines( field, func ); | 
|---|
| [b32ada31] | 267 | } | 
|---|
|  | 268 |  | 
|---|
| [bcda04c] | 269 | FunctionDecl * ConcurrentSueKeyword::forwardDeclare( StructDecl * decl ) { | 
|---|
|  | 270 |  | 
|---|
|  | 271 | StructDecl * forward = decl->clone(); | 
|---|
|  | 272 | forward->set_body( false ); | 
|---|
|  | 273 | deleteAll( forward->get_members() ); | 
|---|
|  | 274 | forward->get_members().clear(); | 
|---|
|  | 275 |  | 
|---|
| [bd4d011] | 276 | FunctionType * get_type = new FunctionType( noQualifiers, false ); | 
|---|
| [bcda04c] | 277 | ObjectDecl * this_decl = new ObjectDecl( | 
|---|
|  | 278 | "this", | 
|---|
| [b32ada31] | 279 | noStorage, | 
|---|
|  | 280 | LinkageSpec::Cforall, | 
|---|
|  | 281 | nullptr, | 
|---|
| [bcda04c] | 282 | new PointerType( | 
|---|
| [b32ada31] | 283 | noQualifiers, | 
|---|
| [bcda04c] | 284 | new StructInstType( | 
|---|
|  | 285 | noQualifiers, | 
|---|
|  | 286 | decl | 
|---|
|  | 287 | ) | 
|---|
| [b32ada31] | 288 | ), | 
|---|
|  | 289 | nullptr | 
|---|
|  | 290 | ); | 
|---|
|  | 291 |  | 
|---|
| [bd4d011] | 292 | get_type->get_parameters().push_back( this_decl ); | 
|---|
|  | 293 | get_type->get_returnVals().push_back( | 
|---|
| [e04b636] | 294 | new ObjectDecl( | 
|---|
|  | 295 | "ret", | 
|---|
|  | 296 | noStorage, | 
|---|
|  | 297 | LinkageSpec::Cforall, | 
|---|
|  | 298 | nullptr, | 
|---|
|  | 299 | new PointerType( | 
|---|
|  | 300 | noQualifiers, | 
|---|
|  | 301 | new StructInstType( | 
|---|
|  | 302 | noQualifiers, | 
|---|
| [bcda04c] | 303 | type_decl | 
|---|
| [e04b636] | 304 | ) | 
|---|
|  | 305 | ), | 
|---|
|  | 306 | nullptr | 
|---|
|  | 307 | ) | 
|---|
|  | 308 | ); | 
|---|
| [b32ada31] | 309 |  | 
|---|
| [bcda04c] | 310 | FunctionDecl * get_decl = new FunctionDecl( | 
|---|
|  | 311 | getter_name, | 
|---|
|  | 312 | Type::Static, | 
|---|
|  | 313 | LinkageSpec::Cforall, | 
|---|
| [bd4d011] | 314 | get_type, | 
|---|
| [bcda04c] | 315 | nullptr, | 
|---|
|  | 316 | noAttributes, | 
|---|
|  | 317 | Type::Inline | 
|---|
|  | 318 | ); | 
|---|
|  | 319 |  | 
|---|
| [bd4d011] | 320 | FunctionDecl * main_decl = nullptr; | 
|---|
|  | 321 |  | 
|---|
|  | 322 | if( needs_main ) { | 
|---|
|  | 323 | FunctionType * main_type = new FunctionType( noQualifiers, false ); | 
|---|
|  | 324 |  | 
|---|
|  | 325 | main_type->get_parameters().push_back( this_decl->clone() ); | 
|---|
|  | 326 |  | 
|---|
|  | 327 | main_decl = new FunctionDecl( | 
|---|
|  | 328 | "main", | 
|---|
|  | 329 | noStorage, | 
|---|
|  | 330 | LinkageSpec::Cforall, | 
|---|
|  | 331 | main_type, | 
|---|
|  | 332 | nullptr | 
|---|
|  | 333 | ); | 
|---|
|  | 334 | } | 
|---|
|  | 335 |  | 
|---|
| [bcda04c] | 336 | declsToAdd.push_back( forward ); | 
|---|
| [bd4d011] | 337 | if( needs_main ) declsToAdd.push_back( main_decl ); | 
|---|
| [bcda04c] | 338 | declsToAdd.push_back( get_decl ); | 
|---|
|  | 339 |  | 
|---|
|  | 340 | return get_decl; | 
|---|
|  | 341 | } | 
|---|
|  | 342 |  | 
|---|
|  | 343 | ObjectDecl * ConcurrentSueKeyword::addField( StructDecl * decl ) { | 
|---|
|  | 344 | ObjectDecl * field = new ObjectDecl( | 
|---|
|  | 345 | field_name, | 
|---|
|  | 346 | noStorage, | 
|---|
|  | 347 | LinkageSpec::Cforall, | 
|---|
|  | 348 | nullptr, | 
|---|
|  | 349 | new StructInstType( | 
|---|
|  | 350 | noQualifiers, | 
|---|
|  | 351 | type_decl | 
|---|
|  | 352 | ), | 
|---|
|  | 353 | nullptr | 
|---|
|  | 354 | ); | 
|---|
|  | 355 |  | 
|---|
|  | 356 | decl->get_members().push_back( field ); | 
|---|
|  | 357 |  | 
|---|
|  | 358 | return field; | 
|---|
|  | 359 | } | 
|---|
|  | 360 |  | 
|---|
| [2f9a722] | 361 | void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) { | 
|---|
| [b32ada31] | 362 | CompoundStmt * statement = new CompoundStmt( noLabels ); | 
|---|
|  | 363 | statement->push_back( | 
|---|
|  | 364 | new ReturnStmt( | 
|---|
|  | 365 | noLabels, | 
|---|
| [e04b636] | 366 | new AddressExpr( | 
|---|
| [bcda04c] | 367 | new MemberExpr( | 
|---|
|  | 368 | field, | 
|---|
|  | 369 | UntypedExpr::createDeref( new VariableExpr( func->get_functionType()->get_parameters().front() ) ) | 
|---|
| [e04b636] | 370 | ) | 
|---|
| [b32ada31] | 371 | ) | 
|---|
|  | 372 | ) | 
|---|
|  | 373 | ); | 
|---|
|  | 374 |  | 
|---|
| [bcda04c] | 375 | FunctionDecl * get_decl = func->clone(); | 
|---|
|  | 376 |  | 
|---|
|  | 377 | get_decl->set_statements( statement ); | 
|---|
| [e04b636] | 378 |  | 
|---|
|  | 379 | declsToAddAfter.push_back( get_decl ); | 
|---|
|  | 380 |  | 
|---|
| [bcda04c] | 381 | // get_decl->fixUniqueId(); | 
|---|
| [b32ada31] | 382 | } | 
|---|
|  | 383 |  | 
|---|
| [64adb03] | 384 | //============================================================================================= | 
|---|
|  | 385 | // Mutex keyword implementation | 
|---|
|  | 386 | //============================================================================================= | 
|---|
|  | 387 | void MutexKeyword::visit(FunctionDecl* decl) { | 
|---|
| [102a58b] | 388 | Visitor::visit(decl); | 
|---|
|  | 389 |  | 
|---|
| [64adb03] | 390 | std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl ); | 
|---|
|  | 391 | if( mutexArgs.empty() ) return; | 
|---|
|  | 392 |  | 
|---|
|  | 393 | for(auto arg : mutexArgs) { | 
|---|
|  | 394 | validate( arg ); | 
|---|
|  | 395 | } | 
|---|
|  | 396 |  | 
|---|
|  | 397 | CompoundStmt* body = decl->get_statements(); | 
|---|
|  | 398 | if( ! body ) return; | 
|---|
|  | 399 |  | 
|---|
| [b32ada31] | 400 | if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl ); | 
|---|
|  | 401 | if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl ); | 
|---|
|  | 402 |  | 
|---|
| [64adb03] | 403 | addStatments( body, mutexArgs ); | 
|---|
|  | 404 | } | 
|---|
|  | 405 |  | 
|---|
| [9243cc91] | 406 | void MutexKeyword::visit(StructDecl* decl) { | 
|---|
| [102a58b] | 407 | Visitor::visit(decl); | 
|---|
|  | 408 |  | 
|---|
| [9243cc91] | 409 | if( decl->get_name() == "monitor_desc" ) { | 
|---|
|  | 410 | assert( !monitor_decl ); | 
|---|
|  | 411 | monitor_decl = decl; | 
|---|
|  | 412 | } | 
|---|
| [ef42b143] | 413 | else if( decl->get_name() == "monitor_guard_t" ) { | 
|---|
|  | 414 | assert( !guard_decl ); | 
|---|
|  | 415 | guard_decl = decl; | 
|---|
|  | 416 | } | 
|---|
| [9243cc91] | 417 | } | 
|---|
|  | 418 |  | 
|---|
| [64adb03] | 419 | std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) { | 
|---|
|  | 420 | std::list<DeclarationWithType*> mutexArgs; | 
|---|
|  | 421 |  | 
|---|
|  | 422 | for( auto arg : decl->get_functionType()->get_parameters()) { | 
|---|
|  | 423 | //Find mutex arguments | 
|---|
|  | 424 | Type* ty = arg->get_type(); | 
|---|
| [615a096] | 425 | if( ! ty->get_mutex() ) continue; | 
|---|
| [64adb03] | 426 |  | 
|---|
|  | 427 | //Append it to the list | 
|---|
|  | 428 | mutexArgs.push_back( arg ); | 
|---|
|  | 429 | } | 
|---|
|  | 430 |  | 
|---|
|  | 431 | return mutexArgs; | 
|---|
|  | 432 | } | 
|---|
|  | 433 |  | 
|---|
|  | 434 | void MutexKeyword::validate( DeclarationWithType * arg ) { | 
|---|
|  | 435 | Type* ty = arg->get_type(); | 
|---|
|  | 436 |  | 
|---|
|  | 437 | //Makes sure it's not a copy | 
|---|
|  | 438 | PointerType* pty = dynamic_cast< PointerType * >( ty ); | 
|---|
|  | 439 | if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg ); | 
|---|
|  | 440 |  | 
|---|
|  | 441 | //Make sure the we are pointing directly to a type | 
|---|
|  | 442 | Type* base = pty->get_base(); | 
|---|
|  | 443 | if(  dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg ); | 
|---|
|  | 444 |  | 
|---|
|  | 445 | //Make sure that typed isn't mutex | 
|---|
| [e04b636] | 446 | if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg ); | 
|---|
| [64adb03] | 447 | } | 
|---|
|  | 448 |  | 
|---|
|  | 449 | void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) { | 
|---|
| [9243cc91] | 450 | ObjectDecl * monitors = new ObjectDecl( | 
|---|
|  | 451 | "__monitors", | 
|---|
|  | 452 | noStorage, | 
|---|
|  | 453 | LinkageSpec::Cforall, | 
|---|
|  | 454 | nullptr, | 
|---|
|  | 455 | new ArrayType( | 
|---|
|  | 456 | noQualifiers, | 
|---|
|  | 457 | new PointerType( | 
|---|
|  | 458 | noQualifiers, | 
|---|
|  | 459 | new StructInstType( | 
|---|
|  | 460 | noQualifiers, | 
|---|
|  | 461 | monitor_decl | 
|---|
|  | 462 | ) | 
|---|
|  | 463 | ), | 
|---|
|  | 464 | new ConstantExpr( Constant::from_ulong( args.size() ) ), | 
|---|
|  | 465 | false, | 
|---|
|  | 466 | false | 
|---|
|  | 467 | ), | 
|---|
|  | 468 | new ListInit( | 
|---|
| [cb0e6de] | 469 | map_range < std::list<Initializer*> > ( args, [this](DeclarationWithType * var ){ | 
|---|
|  | 470 | Type * type = var->get_type()->clone(); | 
|---|
|  | 471 | type->set_mutex( false ); | 
|---|
| [9243cc91] | 472 | return new SingleInit( new UntypedExpr( | 
|---|
|  | 473 | new NameExpr( "get_monitor" ), | 
|---|
| [cb0e6de] | 474 | {  new CastExpr( new VariableExpr( var ), type ) } | 
|---|
| [9243cc91] | 475 | ) ); | 
|---|
|  | 476 | }) | 
|---|
|  | 477 | ) | 
|---|
|  | 478 | ); | 
|---|
|  | 479 |  | 
|---|
| [64adb03] | 480 | //in reverse order : | 
|---|
|  | 481 | // monitor_guard_t __guard = { __monitors, # }; | 
|---|
|  | 482 | body->push_front( | 
|---|
|  | 483 | new DeclStmt( noLabels, new ObjectDecl( | 
|---|
|  | 484 | "__guard", | 
|---|
|  | 485 | noStorage, | 
|---|
|  | 486 | LinkageSpec::Cforall, | 
|---|
|  | 487 | nullptr, | 
|---|
|  | 488 | new StructInstType( | 
|---|
|  | 489 | noQualifiers, | 
|---|
| [ef42b143] | 490 | guard_decl | 
|---|
| [64adb03] | 491 | ), | 
|---|
|  | 492 | new ListInit( | 
|---|
|  | 493 | { | 
|---|
| [9243cc91] | 494 | new SingleInit( new VariableExpr( monitors ) ), | 
|---|
| [64adb03] | 495 | new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ) | 
|---|
| [ef42b143] | 496 | }, | 
|---|
|  | 497 | noDesignators, | 
|---|
|  | 498 | true | 
|---|
| [64adb03] | 499 | ) | 
|---|
|  | 500 | )) | 
|---|
|  | 501 | ); | 
|---|
|  | 502 |  | 
|---|
| [ef42b143] | 503 | //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) }; | 
|---|
| [9243cc91] | 504 | body->push_front( new DeclStmt( noLabels, monitors) ); | 
|---|
| [64adb03] | 505 | } | 
|---|
| [bd4d011] | 506 |  | 
|---|
|  | 507 | //============================================================================================= | 
|---|
|  | 508 | // General entry routine | 
|---|
|  | 509 | //============================================================================================= | 
|---|
|  | 510 | void ThreadStarter::visit(FunctionDecl * decl) { | 
|---|
| [102a58b] | 511 | Visitor::visit(decl); | 
|---|
|  | 512 |  | 
|---|
| [bd4d011] | 513 | if( ! InitTweak::isConstructor(decl->get_name()) ) return; | 
|---|
|  | 514 |  | 
|---|
|  | 515 | DeclarationWithType * param = decl->get_functionType()->get_parameters().front(); | 
|---|
|  | 516 | auto ptr = dynamic_cast< PointerType * >( param->get_type() ); | 
|---|
|  | 517 | // if( ptr ) std::cerr << "FRED1" << std::endl; | 
|---|
|  | 518 | auto type  = dynamic_cast< StructInstType * >( ptr->get_base() ); | 
|---|
|  | 519 | // if( type ) std::cerr << "FRED2" << std::endl; | 
|---|
|  | 520 | if( type && type->get_baseStruct()->is_thread() ) { | 
|---|
|  | 521 | addStartStatement( decl, param ); | 
|---|
|  | 522 | } | 
|---|
|  | 523 | } | 
|---|
|  | 524 |  | 
|---|
|  | 525 | void ThreadStarter::addStartStatement( FunctionDecl * decl, DeclarationWithType * param ) { | 
|---|
|  | 526 | CompoundStmt * stmt = decl->get_statements(); | 
|---|
|  | 527 |  | 
|---|
|  | 528 | if( ! stmt ) return; | 
|---|
|  | 529 |  | 
|---|
|  | 530 | stmt->push_back( | 
|---|
|  | 531 | new ExprStmt( | 
|---|
|  | 532 | noLabels, | 
|---|
|  | 533 | new UntypedExpr( | 
|---|
|  | 534 | new NameExpr( "__thrd_start" ), | 
|---|
|  | 535 | { new VariableExpr( param ) } | 
|---|
|  | 536 | ) | 
|---|
|  | 537 | ) | 
|---|
|  | 538 | ); | 
|---|
|  | 539 | } | 
|---|
| [68fe077a] | 540 | }; | 
|---|