Changeset 00675a1


Ignore:
Timestamp:
May 10, 2022, 12:25:05 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, master, pthread-emulation, qualifiedEnum
Children:
8faa6612
Parents:
3b80db8 (diff), 7edd5c1 (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
4 added
19 edited

Legend:

Unmodified
Added
Removed
  • benchmark/plot.py

    r3b80db8 r00675a1  
    3333        "Ops per threads"       : Field('Ops'   , 0, False),
    3434        "ns per ops/procs"      : Field('ns'    , 0, False),
    35         "Number of threads"     : Field('thrd'  , 1, False),
     35        "Number of threads"     : Field(''      , 1, False),
    3636        "Total Operations(ops)" : Field('Ops'   , 0, False),
    3737        "Ops/sec/procs"         : Field('Ops'   , 0, False),
     
    4040        "Cycle size (# thrds)"  : Field('thrd'  , 1, False),
    4141        "Duration (ms)"         : Field('ms'    , 0, False),
    42         "Target QPS"            : Field('QPS'   , 0, False),
    43         "Actual QPS"            : Field('QPS'   , 0, False),
     42        "Target QPS"            : Field(''      , 0, False),
     43        "Actual QPS"            : Field(''      , 0, False),
     44        "Average Read Latency"  : Field('us'    , 0, True),
    4445        "Median Read Latency"   : Field('us'    , 0, True),
    4546        "Tail Read Latency"     : Field('us'    , 0, True),
     47        "Average Update Latency": Field('us'    , 0, True),
    4648        "Median Update Latency" : Field('us'    , 0, True),
    4749        "Tail Update Latency"   : Field('us'    , 0, True),
     50        "Update Ratio"          : Field('\%'    , 0, False),
    4851}
    4952
     
    9295        print("Making Plots")
    9396
    94         for name, data in series.items():
     97        for name, data in sorted(series.items()):
    9598                _col = next(colors)
    9699                plt.scatter(data['x'], data['y'], color=_col, label=name, marker='x')
  • benchmark/process-mutilate.py

    r3b80db8 r00675a1  
    1414parser = argparse.ArgumentParser(description='Python Script to convert output from mutilate to rmit like output')
    1515parser.add_argument('--out', nargs='?', type=argparse.FileType('w'), default=sys.stdout)
     16parser.add_argument('--var', nargs='?', type=str, default='Target QPS')
    1617try:
    1718        options =  parser.parse_args()
     
    3132
    3233        try:
     34                latAvs = fields[1]
    3335                lat50s = fields[6]
    3436                lat99s = fields[9]
     
    3739
    3840        try:
     41                latAv = locale.atof(latAvs)
    3942                lat50 = locale.atof(lat50s)
    4043                lat99 = locale.atof(lat99s)
     
    4245                raise Warning("Warning: \"{}\" \"{}\"! can't convert to float".format(lat50s, lat99s))
    4346
    44         return lat50, lat99
     47        return latAv, lat50, lat99
    4548
    4649def want0(line):
     
    5861                try:
    5962                        if   line.startswith("read"):
    60                                 rlat50, rlat99 = precentile(line)
     63                                rlatAv, rlat50, rlat99 = precentile(line)
    6164
    6265                        elif line.startswith("update"):
    63                                 ulat50, ulat99 = precentile(line)
     66                                ulatAv, ulat50, ulat99 = precentile(line)
    6467
    6568                        elif line.startswith("Total QPS"):
     
    8487
    8588        try:
     89                out['Average Read Latency'] = rlatAv
    8690                out['Median Read Latency'] = rlat50
    8791                out['Tail Read Latency'] = rlat99
     
    9094
    9195        try:
     96                out['Average Update Latency'] = ulatAv
    9297                out['Median Update Latency'] = ulat50
    9398                out['Tail Update Latency'] = ulat99
     
    112117                        continue
    113118
    114                 d = { 'Target QPS': int(rate) }
     119                d = { options.var : int(rate) }
    115120
    116121                w = extract( f, d )
  • libcfa/src/concurrency/io.cfa

    r3b80db8 r00675a1  
    244244
    245245                                        remote = true;
    246                                         __STATS__( false, io.calls.helped++; )
     246                                        __STATS__( true, io.calls.helped++; )
    247247                                }
    248248                                proc->io.target = MAX;
  • libcfa/src/concurrency/locks.cfa

    r3b80db8 r00675a1  
    220220
    221221//-----------------------------------------------------------------------------
    222 // condition variable
     222// Synchronization Locks
    223223forall(L & | is_blocking_lock(L)) {
    224224
     225        //-----------------------------------------------------------------------------
     226        // condition variable
    225227        void ?{}( condition_variable(L) & this ){
    226228                this.lock{};
     
    337339        bool wait( condition_variable(L) & this, L & l, Duration duration                 ) with(this) { WAIT_TIME( 0   , &l , duration ) }
    338340        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration ) with(this) { WAIT_TIME( info, &l , duration ) }
     341
     342        //-----------------------------------------------------------------------------
     343        // fast_cond_var
     344        void  ?{}( fast_cond_var(L) & this ){
     345                this.blocked_threads{};
     346                #ifdef __CFA_DEBUG__
     347                this.lock_used = 0p;
     348                #endif
     349        }
     350        void ^?{}( fast_cond_var(L) & this ){ }
     351
     352        bool notify_one( fast_cond_var(L) & this ) with(this) {
     353                bool ret = ! blocked_threads`isEmpty;
     354                if ( ret ) {
     355                        info_thread(L) & popped = try_pop_front( blocked_threads );
     356                        on_notify(*popped.lock, popped.t);
     357                }
     358                return ret;
     359        }
     360        bool notify_all( fast_cond_var(L) & this ) with(this) {
     361                bool ret = ! blocked_threads`isEmpty;
     362                while( ! blocked_threads`isEmpty ) {
     363                        info_thread(L) & popped = try_pop_front( blocked_threads );
     364                        on_notify(*popped.lock, popped.t);
     365                }
     366                return ret;
     367        }
     368
     369        uintptr_t front( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty ? NULL : blocked_threads`first.info; }
     370        bool empty ( fast_cond_var(L) & this ) with(this) { return blocked_threads`isEmpty; }
     371
     372        void wait( fast_cond_var(L) & this, L & l ) {
     373                wait( this, l, 0 );
     374        }
     375
     376        void wait( fast_cond_var(L) & this, L & l, uintptr_t info ) with(this) {
     377                // brand cond lock with lock
     378                #ifdef __CFA_DEBUG__
     379                        if ( lock_used == 0p ) lock_used = &l;
     380                        else { assert(lock_used == &l); }
     381                #endif
     382                info_thread( L ) i = { active_thread(), info, &l };
     383                insert_last( blocked_threads, i );
     384                size_t recursion_count = on_wait( *i.lock );
     385                park( );
     386                on_wakeup(*i.lock, recursion_count);
     387        }
    339388}
    340389
  • libcfa/src/concurrency/locks.hfa

    r3b80db8 r00675a1  
    7373static inline void   on_notify( owner_lock & this, struct thread$ * t ) { on_notify( (blocking_lock &)this, t ); }
    7474
     75//-----------------------------------------------------------------------------
     76// MCS Lock
    7577struct mcs_node {
    7678        mcs_node * volatile next;
     
    98100}
    99101
     102//-----------------------------------------------------------------------------
     103// Linear backoff Spinlock
    100104struct linear_backoff_then_block_lock {
    101105        // Spin lock used for mutual exclusion
     
    199203
    200204//-----------------------------------------------------------------------------
     205// Fast Block Lock
     206
     207// High efficiency minimal blocking lock
     208// - No reacquire for cond var
     209// - No recursive acquisition
     210// - No ownership
     211struct fast_block_lock {
     212        // Spin lock used for mutual exclusion
     213        __spinlock_t lock;
     214
     215        // List of blocked threads
     216        dlist( thread$ ) blocked_threads;
     217
     218        bool held:1;
     219};
     220
     221static inline void  ?{}( fast_block_lock & this ) with(this) {
     222        lock{};
     223        blocked_threads{};
     224        held = false;
     225}
     226static inline void ^?{}( fast_block_lock & this ) {}
     227static inline void ?{}( fast_block_lock & this, fast_block_lock this2 ) = void;
     228static inline void ?=?( fast_block_lock & this, fast_block_lock this2 ) = void;
     229
     230// if this is called recursively IT WILL DEADLOCK!!!!!
     231static inline void lock(fast_block_lock & this) with(this) {
     232        lock( lock __cfaabi_dbg_ctx2 );
     233        if (held) {
     234                insert_last( blocked_threads, *active_thread() );
     235                unlock( lock );
     236                park( );
     237                return;
     238        }
     239        held = true;
     240        unlock( lock );
     241}
     242
     243static inline void unlock(fast_block_lock & this) with(this) {
     244        lock( lock __cfaabi_dbg_ctx2 );
     245        /* paranoid */ verifyf( held != false, "Attempt to release lock %p that isn't held", &this );
     246        thread$ * t = &try_pop_front( blocked_threads );
     247        held = ( t ? true : false );
     248        unpark( t );
     249        unlock( lock );
     250}
     251
     252static inline void on_notify(fast_block_lock & this, struct thread$ * t ) { unpark(t); }
     253static inline size_t on_wait(fast_block_lock & this) { unlock(this); return 0; }
     254static inline void on_wakeup(fast_block_lock & this, size_t recursion ) { }
     255
     256//-----------------------------------------------------------------------------
    201257// is_blocking_lock
    202258trait is_blocking_lock(L & | sized(L)) {
     
    226282// Synchronization Locks
    227283forall(L & | is_blocking_lock(L)) {
     284
     285        //-----------------------------------------------------------------------------
     286        // condition_variable
     287
     288        // The multi-tool condition variable
     289        // - can pass timeouts to wait for either a signal or timeout
     290        // - can wait without passing a lock
     291        // - can have waiters reacquire different locks while waiting on the same cond var
     292        // - has shadow queue
     293        // - can be signalled outside of critical sections with no locks held
    228294        struct condition_variable {
    229295                // Spin lock used for mutual exclusion
     
    258324        bool wait( condition_variable(L) & this, L & l, Duration duration );
    259325        bool wait( condition_variable(L) & this, L & l, uintptr_t info, Duration duration );
    260 }
     326
     327        //-----------------------------------------------------------------------------
     328        // fast_cond_var
     329
     330        // The trimmed and slim condition variable
     331        // - no internal lock so you must hold a lock while using this cond var
     332        // - signalling without holding branded lock is UNSAFE!
     333        // - only allows usage of one lock, cond var is branded after usage
     334        struct fast_cond_var {
     335                // List of blocked threads
     336                dlist( info_thread(L) ) blocked_threads;
     337
     338                #ifdef __CFA_DEBUG__
     339                L * lock_used;
     340                #endif
     341        };
     342
     343
     344        void  ?{}( fast_cond_var(L) & this );
     345        void ^?{}( fast_cond_var(L) & this );
     346
     347        bool notify_one( fast_cond_var(L) & this );
     348        bool notify_all( fast_cond_var(L) & this );
     349
     350        uintptr_t front( fast_cond_var(L) & this );
     351
     352        bool empty  ( fast_cond_var(L) & this );
     353
     354        void wait( fast_cond_var(L) & this, L & l );
     355        void wait( fast_cond_var(L) & this, L & l, uintptr_t info );
     356}
  • libcfa/src/concurrency/ready_subqueue.hfa

    r3b80db8 r00675a1  
    8383        /* paranoid */ verify( node->link.ts   != 0  );
    8484        /* paranoid */ verify( this.anchor.ts  != 0  );
     85        /* paranoid */ verify( (this.anchor.ts  == MAX) == is_empty );
    8586        return [node, this.anchor.ts];
    8687}
     
    9394// Return the timestamp
    9495static inline unsigned long long ts(__intrusive_lane_t & this) {
    95         // Cannot verify here since it may not be locked
     96        // Cannot verify 'emptiness' here since it may not be locked
    9697        /* paranoid */ verify(this.anchor.ts != 0);
    9798        return this.anchor.ts;
  • src/AST/Convert.cpp

    r3b80db8 r00675a1  
    9393        };
    9494
    95     template<typename T>
    96     Getter<T> get() {
    97         return Getter<T>{ *this };
    98     }
     95        template<typename T>
     96        Getter<T> get() {
     97                return Getter<T>{ *this };
     98        }
    9999
    100100        Label makeLabel(Statement * labelled, const ast::Label& label) {
     
    16511651                        // GET_ACCEPT_1(type, FunctionType),
    16521652                        std::move(forall),
     1653                        std::move(assertions),
    16531654                        std::move(paramVars),
    16541655                        std::move(returnVars),
     
    16641665                cache.emplace( old, decl );
    16651666
    1666                 decl->assertions = std::move(assertions);
    16671667                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    16681668                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
  • src/AST/Copy.cpp

    r3b80db8 r00675a1  
    1010// Created On       : Thr Nov 11  9:16:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Nov 11  9:28:00 2021
    13 // Update Count     : 0
     12// Last Modified On : Tue May  3 16:28:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    7777        }
    7878
     79        void postvisit( const UniqueExpr * node ) {
     80                readonlyInsert( &node->object );
     81        }
     82
    7983        void postvisit( const MemberExpr * node ) {
    8084                readonlyInsert( &node->member );
  • src/AST/Decl.cpp

    r3b80db8 r00675a1  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jan 12 16:54:55 2021
    13 // Update Count     : 23
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu May  5 12:10:00 2022
     13// Update Count     : 24
    1414//
    1515
     
    5353// --- FunctionDecl
    5454
    55 FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 
     55FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
    5656        std::vector<ptr<TypeDecl>>&& forall,
    5757        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     
    7474        }
    7575        this->type = ftype;
     76}
     77
     78FunctionDecl::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;
    76102}
    77103
  • src/AST/Decl.hpp

    r3b80db8 r00675a1  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 12 18:25:05 2021
    13 // Update Count     : 32
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu May  5 12:09:00 2022
     13// Update Count     : 33
    1414//
    1515
     
    135135        std::vector< ptr<Expr> > withExprs;
    136136
     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
    137143        FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
    138144                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    139145                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    140146                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);
    143153
    144154        const Type * get_type() const override;
  • src/AST/Expr.hpp

    r3b80db8 r00675a1  
    784784public:
    785785        ptr<Expr> expr;
    786         ptr<ObjectDecl> object;
     786        readonly<ObjectDecl> object;
    787787        ptr<VariableExpr> var;
    788788        unsigned long long id;
  • src/AST/Node.hpp

    r3b80db8 r00675a1  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Mar 25 10:33:00 2022
    13 // Update Count     : 7
     12// Last Modified On : Mon May  9 10:20:00 2022
     13// Update Count     : 8
    1414//
    1515
     
    4949
    5050        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; }
    5253
    5354private:
  • src/AST/Stmt.cpp

    r3b80db8 r00675a1  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May  8 13:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 19:01:20 2022
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue May  3 15:18:20 2022
     13// Update Count     : 4
    1414//
    1515
    1616#include "Stmt.hpp"
    1717
    18 
     18#include "Copy.hpp"
    1919#include "DeclReplacer.hpp"
    2020#include "Type.hpp"
     
    2323
    2424// --- CompoundStmt
    25 CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids(other.kids) {
     25CompoundStmt::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
    2638        // when cloning a compound statement, we may end up cloning declarations which
    2739        // are referred to by VariableExprs throughout the block. Cloning a VariableExpr
  • src/Common/SemanticError.h

    r3b80db8 r00675a1  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 19 10:09:17 2018
    13 // Update Count     : 31
     12// Last Modified On : Wed May  4 14:08:26 2022
     13// Update Count     : 35
    1414//
    1515
     
    5959        {"aggregate-forward-decl" , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
    6060        {"superfluous-decl"       , Severity::Warn    , "declaration does not allocate storage: %s"                  },
     61        {"superfluous-else"       , Severity::Warn    , "else clause never executed for empty loop conditional"      },
    6162        {"gcc-attributes"         , Severity::Warn    , "invalid attribute: %s"                                      },
    6263        {"c++-like-copy"          , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
     
    6970        AggrForwardDecl,
    7071        SuperfluousDecl,
     72        SuperfluousElse,
    7173        GccAttributes,
    7274        CppCopy,
     
    7981);
    8082
    81 #define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id].message, __VA_ARGS__)
     83#define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id].message, ##__VA_ARGS__)
    8284
    8385void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4)));
  • src/ControlStruct/MultiLevelExit.cpp

    r3b80db8 r00675a1  
    594594                }
    595595
     596                // check if loop node and if so add else clause if it exists
     597                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
    596602                if ( ! break_label.empty() ) {
    597603                        ret.push_back( labelledNullStmt( ret.back()->location, break_label ) );
  • src/Parser/parser.yy

    r3b80db8 r00675a1  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 14 16:35:29 2022
    13 // Update Count     : 5276
     12// Last Modified On : Wed May  4 17:22:48 2022
     13// Update Count     : 5279
    1414//
    1515
     
    111111
    112112void distInl( DeclarationNode * declaration ) {
    113         // distribute EXTENSION across all declarations
     113        // distribute INLINE across all declarations
    114114        for ( DeclarationNode *iter = declaration; iter != nullptr; iter = (DeclarationNode *)iter->get_next() ) {
    115115                iter->set_inLine( true );
     
    12211221
    12221222iteration_statement:
    1223         WHILE '(' ')' statement                                                         // CFA => while ( 1 )
     1223        WHILE '(' ')' statement                                                         %prec THEN // CFA => while ( 1 )
    12241224                { $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
     1225        | WHILE '(' ')' statement ELSE statement                        // CFA
     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                }
    12251230        | WHILE '(' conditional_declaration ')' statement       %prec THEN
    12261231                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
     
    12291234        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    12301235                { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
    1231         | DO statement WHILE '(' comma_expression ')' ';'       %prec THEN
     1236        | DO statement WHILE '(' ')' ELSE statement                     // CFA
     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 ')' ';'
    12321242                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    12331243        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    12341244                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
    1235         | FOR '(' ')' statement                                                         // CFA => for ( ;; )
     1245        | FOR '(' ')' statement                                                         %prec THEN // CFA => for ( ;; )
    12361246                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
     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                }
    12371252        | FOR '(' for_control_expression_list ')' statement     %prec THEN
    12381253                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
     
    23182333                        { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    23192334
    2320                         $$ = DeclarationNode::newEnum( nullptr, $7, true, $3 ) ->addQualifiers( $5 );
     2335                        $$ = DeclarationNode::newEnum( nullptr, $7, true, $3 )->addQualifiers( $5 );
    23212336                }
    23222337        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
     
    23272342          '{' enumerator_list comma_opt '}'
    23282343                {
    2329                         $$ = DeclarationNode::newEnum( $6, $10, true, $3 ) -> addQualifiers( $5 ) -> addQualifiers( $7 );
     2344                        $$ = DeclarationNode::newEnum( $6, $10, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
    23302345                }
    23312346        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt '{' enumerator_list comma_opt '}'
     
    23332348                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    23342349                        typedefTable.makeTypedef( *$6->name );
    2335                         $$ = DeclarationNode::newEnum( $6->name, $9, true, $3 ) -> addQualifiers( $5 ) -> addQualifiers( $7 );
     2350                        $$ = DeclarationNode::newEnum( $6->name, $9, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
    23362351                }
    23372352        | enum_type_nobody
  • src/Validate/Autogen.cpp

    r3b80db8 r00675a1  
    350350                name,
    351351                std::move( type_params ),
     352                std::move( assertions ),
    352353                std::move( params ),
    353354                std::move( returns ),
     
    360361                // Auto-generated routines are inline to avoid conflicts.
    361362                ast::Function::Specs( ast::Function::Inline ) );
    362         decl->assertions = std::move( assertions );
    363363        decl->fixUniqueId();
    364364        return decl;
  • tests/unified_locking/.expect/locks.txt

    r3b80db8 r00675a1  
    2323Start Test 12: locked condition variable wait/notify with front()
    2424Done Test 12
     25Start Test 13: fast block lock and fast cond var single wait/notify
     26Done Test 13
  • tests/unified_locking/locks.cfa

    r3b80db8 r00675a1  
    1818condition_variable( linear_backoff_then_block_lock ) c_l;
    1919
     20fast_block_lock f;
     21fast_cond_var( fast_block_lock ) f_c_f;
     22
    2023thread T_C_M_WS1 {};
    2124
     
    99102                }
    100103                unlock(l);
     104        }
     105}
     106
     107thread T_F_C_F_WS1 {};
     108
     109void main( T_F_C_F_WS1 & this ) {
     110        for (unsigned int i = 0; i < num_times; i++) {
     111                lock(f);
     112                if(empty(f_c_f) && i != num_times - 1) {
     113                        wait(f_c_f,f);
     114                }else{
     115                        notify_one(f_c_f);
     116                        unlock(f);
     117                }
    101118        }
    102119}
     
    322339        }
    323340        printf("Done Test 12\n");
    324 }
     341
     342        printf("Start Test 13: fast block lock and fast cond var single wait/notify\n");
     343        {
     344                T_F_C_F_WS1 t1[2];
     345        }
     346        printf("Done Test 13\n");
     347       
     348}
Note: See TracChangeset for help on using the changeset viewer.