Changeset 42cdd07d


Ignore:
Timestamp:
Jun 10, 2024, 2:43:23 AM (4 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
2ab31fd
Parents:
85855b0 (diff), 0188539c (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:
5 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/lstlang.sty

    r85855b0 r42cdd07d  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Mon Apr 15 11:28:44 2024
    11 %% Update Count     : 43
     10%% Last Modified On : Fri May 31 14:36:02 2024
     11%% Update Count     : 44
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    115115        morekeywords={
    116116                alignas, _Alignas, alignof, _Alignof, __alignof, __alignof__, and, asm, __asm, __asm__, _Atomic, __attribute, __attribute__,
    117                 __auto_type, basetypeof, _Bool, catch, catchResume, choose, coerce, corun, cofor, _Complex, __complex, __complex__,
     117                __auto_type, basetypeof, _Bool, bool, catch, catchResume, choose, coerce, corun, cofor, _Complex, __complex, __complex__,
    118118                __const, __const__, continue, coroutine, _Decimal32, _Decimal64, _Decimal128, disable, dtype, enable, exception, __extension__,
    119119                fallthrough, fallthru, finally, fixup, __float80, float80, __float128, float128, _Float16, _Float32, _Float32x, _Float64,
  • doc/bibliography/pl.bib

    r85855b0 r42cdd07d  
    813813    title       = {The Art of Multiprocessor Programming},
    814814    year        = 2008,
    815     isbn        = {0123705916, 9780123705914},
    816815    publisher   = {Morgan Kaufmann Publishers},
    817816    address     = {San Francisco},
     
    928927    month       = sep,
    929928    year        = 2013,
    930     pages       = {46--53},
     929    pages       = {46-53},
    931930    publisher   = {ACM},
    932931    address     = {New York, NY, USA},
     932}
     933
     934@inproceedings{Aravind18,
     935    contributer = {pabuhr@plg},
     936    author      = {Alex Aravind},
     937    title       = {Barrier Synchronization: Simplified, Generalized, and Solved without Mutual Exclusion},
     938    organization= {IEEE International Parallel and Distributed Processing Symposium Workshops},
     939    series      = {IPDPSW'18},
     940    month       = may,
     941    year        = 2018,
     942    pages       = {773-782},
    933943}
    934944
     
    11061116    publisher   = {ACM},
    11071117    address     = {New York, NY, USA},
     1118}
     1119
     1120@article{Brooks87,
     1121    author      = {Eugene D. Brooks III},
     1122    title       = {The Butterfly Barrier},
     1123    journal     = {International Journal of Parallel Programming},
     1124    volume      = 15,
     1125    number      = 4,
     1126    pages       = {295-307},
     1127    year        = 1987,
    11081128}
    11091129
     
    43404360    chapter     = {1},
    43414361    publisher   = {The MIT Press}
     4362}
     4363
     4364@article{Lamport08,
     4365    keywords    = {concurrency, barrier},
     4366    contributer = {pabuhr@plg},
     4367    author      = {Leslie Lamport},
     4368    title       = {Implementing Dataflow with Threads},
     4369    journal     = {Distributed Computing},
     4370    year        = 2008,
     4371    month       = jul,
     4372    volume      = 21,
     4373    number      = 3,
     4374    pages       = {163-181},
    43424375}
    43434376
     
    51715204    journal     = {ACM Trans. Parallel Comput.},
    51725205    issn        = {2329-4949},
    5173     url         = {https://doi.org/10.1145/3584696},
    5174     doi         = {10.1145/3584696},
    51755206    articleno   = 11,
    51765207    numpages    = 23,
     
    77697800}
    77707801
     7802@book{Scott24,
     7803    author      = {Michael L. Scott and Trevor Brown},
     7804    booktitle   = {Shared-Memory Synchronization},
     7805    series      = {Synthesis Lectures on Computer Architecture},
     7806    edition     = {2nd},
     7807    year        = 2024,
     7808    publisher   = {Springer International Publishing},
     7809    address     = {Cham, Switzerland},
     7810}
     7811
    77717812@inproceedings{Leissa14,
    77727813    title       = {{S}ierra: a {SIMD} extension for {C}++},
     
    86618702}
    86628703
     8704@article{Hensgen88,
     8705    author      = {Debra Hensgen and Raphael Finkel and Udi Manber},
     8706    title       = {Two algorithms for barrier synchronization},
     8707    journal     = {International Journal of Parallel Programming},
     8708    volume      = 17,
     8709    number      = 1,
     8710    pages       = {1-17},
     8711    year        = 1988,
     8712}
     8713
    86638714@article{Leroy00,
    86648715    keywords    = {type-systems, exceptions},
     
    87528803    title       = {Understanding Control Flow: Concurrent Programming using $\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}}},
    87538804    publisher   = {Springer},
    8754     address     = {Switzerland},
     8805    address     = {Cham, Switzerland},
    87558806    year        = 2016,
    87568807}
  • doc/proposals/modules.md

    r85855b0 r42cdd07d  
    55======================
    66
    7 Modules are a term for the base in separate compilation. Different languages have different ways to implement it, for C/C++ the module is the code/source file and usually header file.
     7In this proposal we will be descussing modules. Although their exact nature changes between programming languages, modules are the smallest unit of code reuse between programs, or the base unit in separate compilation. Modules, and the extended module system, will be tied up in various stages of compilation and execution, with a particular focus on visibility between different parts of the program.
     8
     9Note that terminology is not fixed across languages. For instance, some languages use the word package or library instead. Module was chosen as the generic term because it seems to have the least amount of other uses (for example, a package is sometimes a group of modules).
     10
     11In C there is no formal definition of module, but informally modules are a pair of files, the body file (.c) and the header (.h). The header provides the interface and the body file gives the implementation. (A translation unit is a source file, usually a .c file, and all the recursively included files.) Some modules, like the main module,
    812
    913Uses of Modules
    1014---------------
    11 The most straight forward purpose of modules is to enable separate compilation.
    12 This in turn reduces recompilation, by isolating changes, and parallel compilation, but making modules independent.
     15This section covers the features module system to allow for the separatation of code across modules and why
    1316
    14 An related feature is sharing information between modules. Information needed by other modules must be shared. However, avoiding sharing extra information can further isolating changes, and can also reduces the work of compiling a single module.
     17Modules are often, but not always, the means by which a language views source files. There is almost always some kind of parity between modules and source files, with modules being mapped onto one (or a few) source files. Sometimes the use of modules is used to find the approprate source files, requring this parity to be enforced in the language. Other times the parity is just a convention or is enforced for other reasons.
    1518
    16 Modules are also used as a base for other organizational features. Such as namespacing on module names, using the module as a space for visibility modifiers.
     19[]
     20
     21If there is a universal feature of modules, it is information visibility. Modules decide what information within them is visible to other modules. Here visibility is the course grained sense of "visible in another module for any purpose".
     22
     23[]
     24
     25Accessablity is the more fine grained partner to visibility, allowing for information to be visible, but only usable for certain purposes. This includes privacy and friendship - only usable in certain parts of the program - or inlining information - only usable by the optimizer.
     26
     27In languages that have namespacing/qualified-names, modules will often interact with namespaces. Such as each module placing its declarations in a namespace of the same name.
    1728
    1829C Comparisons
     
    8091Second, this does nothing to solve the oversized header issue. It does not reduce any requirements on what includes need to be use.
    8192
     93Alternate Solutions
     94-------------------
     95There are other ways C's modules could be improved in Cforall.
     96
     97Explicit Module Blocks
     98......................
     99Instead of trying map files to modules, they could instead be declared explicitly. Marking out the beginning and the end of a section of code as a module. If built on top of the body/header and include system might look like this.
     100
     101>   extern module NAME {
     102>       BODY
     103>   }
     104>
     105>   module NAME {
     106>       BODY
     107>   }
     108
     109The extern module goes in the header, the other module goes in the body. The basic usage is the forward declarations in the header module and the body contains the definitions. It can be used to check that the two sets match, but on its own it is only replicates the current header/body divide with a bit more explicit syntax. However, it can be used as the base for a lot of features of the module linkage system. It does solve the "knowning two declarations came from the same other module" problem (and could work with namespaces) but is otherwise very similar for a heavier syntax.
     110
     111Compiled Headers
     112................
     113Most programming languages do not share source code between modules. Instead each module is compiled without looking at the source code in other modules. The result of compilation includes all the information required for later stages of compilation and information for compiling other modules.
     114
     115This is a more popular pattern more recent programming languages. It does have some advantages, such as reducing the amount of times that a file will need to be processed and can cut out unneeded transitive information. It is downsides include adding dependences between modules and it prevents any circlar dependences between modules.
     116
     117There is one other notable downside, and that is retrofitting this pattern on top of C. The problems with GCC precompiled headers and C++ modules give some indication of how tricky the situation is. The problem is the C pre-processor, not only is this the tool by which modules are implemented, but they contain information for the preprocessor itself, such as macros. Macro definitions must also be applied to the text of source files and so must be preserved. This might be possible in cases with strict dependences from the included file, but there are more unusual uses where macros depend on their context (previous includes or a define before the include) in their definition and these would almost imposible to translate over.
    82118
    83119##########################################################################################
     
    86122----'
    87123
    88 Programming languages are divided into those embedded in an IDE, think Smalltalk and Racket, largely manipulating a symbol-table/abstract-symbol-tree, and those where the IDE is an external program largely manipulating program text.
     124Programming languages are divided into those embedded in an IDE, think Smalltalk and Lisp, Database, largely manipulating a symbol-table/abstract-symbol-tree, and those where the IDE is an external program largely manipulating program text.
    89125Separate compilation in programming languages without an embedded IDE is the process of giving a compiler command a series of files that are read and processed as a whole.
    90126The compiler output is placed in another set of files for execution loading or further processing.
     
    97133In a file system where file-links can be embedded in data creating a tree, duplicate source code can be eliminated by generating a complex linking structure among the source files.
    98134Without embedded file-links, dynamic embedding using #include/import is necessary to compose all the program components necessary for a compilation.
     135
     136inlining?
    99137
    100138I see two separate issues with respect to program structuring for controlling visibility and initializing a program.
  • src/InitTweak/GenInit.cpp

    r85855b0 r42cdd07d  
    3232#include "Common/ToString.hpp"         // for toCString
    3333#include "Common/UniqueName.hpp"       // for UniqueName
    34 #include "Common/Utility.hpp"          // for ValueGuard, maybeClone
    3534#include "GenPoly/GenPoly.hpp"         // for getFunctionType, isPolyType
    3635#include "GenPoly/ScopedSet.hpp"       // for ScopedSet, ScopedSet<>::const_iter...
     
    277276        }
    278277        // need to clear and reset qualifiers when determining if a type is managed
    279         // ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
    280278        auto tmp = shallowCopy(type);
    281279        tmp->qualifiers = {};
  • src/Tuples/TupleAssignment.cpp

    r85855b0 r42cdd07d  
    241241        ResolvExpr::CandidateFinder & crntFinder;
    242242        std::string fname;
    243         std::unique_ptr< Matcher > matcher;
    244243
    245244public:
    246245        TupleAssignSpotter( ResolvExpr::CandidateFinder & f )
    247         : crntFinder( f ), fname(), matcher() {}
    248 
    249         // Find left- and right-hand-sides for mass or multiple assignment.
     246        : crntFinder( f ), fname() {}
     247
     248        /// Find left- and right-hand-sides for mass or multiple assignment.
    250249        void spot(
    251250                const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
    252         ) {
    253                 if ( auto op = expr->func.as< ast::NameExpr >() ) {
    254                         // Skip non-assignment functions.
    255                         if ( !CodeGen::isCtorDtorAssign( op->name ) ) return;
    256                         fname = op->name;
    257 
    258                         // Handled by CandidateFinder if applicable (both odd cases).
    259                         if ( args.empty() || ( 1 == args.size() && CodeGen::isAssignment( fname ) ) ) {
    260                                 return;
    261                         }
    262 
    263                         // Look over all possible left-hand-side.
    264                         for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) {
    265                                 // Skip non-tuple LHS.
    266                                 if ( !refToTuple( lhsCand->expr ) ) continue;
    267 
    268                                 // Explode is aware of casts - ensure every LHS
    269                                 // is sent into explode with a reference cast.
    270                                 if ( !lhsCand->expr.as< ast::CastExpr >() ) {
    271                                         lhsCand->expr = new ast::CastExpr(
    272                                                 lhsCand->expr, new ast::ReferenceType( lhsCand->expr->result ) );
     251        );
     252        /// Wrapper around matcher.match.
     253        void match( Matcher & matcher );
     254};
     255
     256void TupleAssignSpotter::spot(
     257        const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
     258) {
     259        // Skip non-"assignment" functions.
     260        auto op = expr->func.as< ast::NameExpr >();
     261        if ( nullptr == op || !CodeGen::isCtorDtorAssign( op->name ) ) return;
     262
     263        // Handled by CandidateFinder if applicable (both odd cases).
     264        if ( args.empty() || ( 1 == args.size() && CodeGen::isAssignment( op->name ) ) ) {
     265                return;
     266        }
     267
     268        fname = op->name;
     269
     270        // Look over all possible left-hand-side.
     271        for ( ResolvExpr::CandidateRef & lhsCand : args[0] ) {
     272                // Skip non-tuple LHS.
     273                if ( !refToTuple( lhsCand->expr ) ) continue;
     274
     275                // Explode is aware of casts - ensure every LHS
     276                // is sent into explode with a reference cast.
     277                if ( !lhsCand->expr.as< ast::CastExpr >() ) {
     278                        lhsCand->expr = new ast::CastExpr(
     279                                lhsCand->expr, new ast::ReferenceType( lhsCand->expr->result ) );
     280                }
     281
     282                // Explode the LHS so that each field of a tuple-valued expr is assigned.
     283                ResolvExpr::CandidateList lhs;
     284                explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true );
     285                for ( ResolvExpr::CandidateRef & cand : lhs ) {
     286                        // Each LHS value must be a reference - some come in
     287                        // with a cast, if not just cast to reference here.
     288                        if ( !cand->expr->result.as< ast::ReferenceType >() ) {
     289                                cand->expr = new ast::CastExpr(
     290                                        cand->expr, new ast::ReferenceType( cand->expr->result ) );
     291                        }
     292                }
     293
     294                if ( 1 == args.size() ) {
     295                        // Mass default-initialization/destruction.
     296                        ResolvExpr::CandidateList rhs{};
     297                        MassAssignMatcher matcher( *this, expr->location, lhs, rhs );
     298                        match( matcher );
     299                } else if ( 2 == args.size() ) {
     300                        for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) {
     301                                ResolvExpr::CandidateList rhs;
     302                                if ( isTuple( rhsCand->expr ) ) {
     303                                        // Multiple assignment:
     304                                        explode( *rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true );
     305                                        MultipleAssignMatcher matcher( *this, expr->location, lhs, rhs );
     306                                        match( matcher );
     307                                } else {
     308                                        // Mass assignment:
     309                                        rhs.emplace_back( rhsCand );
     310                                        MassAssignMatcher matcher( *this, expr->location, lhs, rhs );
     311                                        match( matcher );
    273312                                }
    274 
    275                                 // Explode the LHS so that each field of a tuple-valued expr is assigned.
    276                                 ResolvExpr::CandidateList lhs;
    277                                 explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true );
    278                                 for ( ResolvExpr::CandidateRef & cand : lhs ) {
    279                                         // Each LHS value must be a reference - some come in
    280                                         // with a cast, if not just cast to reference here.
    281                                         if ( !cand->expr->result.as< ast::ReferenceType >() ) {
    282                                                 cand->expr = new ast::CastExpr(
    283                                                         cand->expr, new ast::ReferenceType( cand->expr->result ) );
    284                                         }
    285                                 }
    286 
    287                                 if ( 1 == args.size() ) {
    288                                         // Mass default-initialization/destruction.
    289                                         ResolvExpr::CandidateList rhs{};
    290                                         matcher.reset( new MassAssignMatcher( *this, expr->location, lhs, rhs ) );
    291                                         match();
    292                                 } else if ( 2 == args.size() ) {
    293                                         for ( const ResolvExpr::CandidateRef & rhsCand : args[1] ) {
    294                                                 ResolvExpr::CandidateList rhs;
    295                                                 if ( isTuple( rhsCand->expr ) ) {
    296                                                         // Multiple assignment:
    297                                                         explode( *rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true );
    298                                                         matcher.reset(
    299                                                                 new MultipleAssignMatcher( *this, expr->location, lhs, rhs ) );
    300                                                 } else {
    301                                                         // Mass assignment:
    302                                                         rhs.emplace_back( rhsCand );
    303                                                         matcher.reset(
    304                                                                 new MassAssignMatcher( *this, expr->location, lhs, rhs ) );
    305                                                 }
    306                                                 match();
    307                                         }
    308                                 } else {
    309                                         // Expand all possible RHS possibilities.
    310                                         std::vector< ResolvExpr::CandidateList > rhsCands;
    311                                         combos(
    312                                                 std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) );
    313                                         for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) {
    314                                                 // Multiple assignment:
    315                                                 ResolvExpr::CandidateList rhs;
    316                                                 explode( rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true );
    317                                                 matcher.reset(
    318                                                         new MultipleAssignMatcher( *this, expr->location, lhs, rhs ) );
    319                                                 match();
    320                                         }
    321                                 }
    322                         }
    323                 }
    324         }
    325 
    326         void match() {
    327                 assert( matcher );
    328 
    329                 std::vector< ast::ptr< ast::Expr > > newAssigns = matcher->match();
    330 
    331                 if ( !( matcher->lhs.empty() && matcher->rhs.empty() ) ) {
    332                         // If both LHS and RHS are empty than this is the empty tuple
    333                         // case, wherein it's okay for newAssigns to be empty. Otherwise,
    334                         // return early so that no new candidates are generated.
    335                         if ( newAssigns.empty() ) return;
    336                 }
    337 
    338                 ResolvExpr::CandidateList crnt;
    339                 // Now resolve new assignments.
    340                 for ( const ast::Expr * expr : newAssigns ) {
    341                         PRINT(
    342                                 std::cerr << "== resolving tuple assign ==" << std::endl;
    343                                 std::cerr << expr << std::endl;
    344                         )
    345 
    346                         ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env );
    347                         finder.allowVoid = true;
    348 
    349                         try {
    350                                 finder.find( expr, ResolvExpr::ResolveMode::withAdjustment() );
    351                         } catch (...) {
    352                                 // No match is not failure, just that this tuple assignment is invalid.
    353                                 return;
    354                         }
    355 
    356                         ResolvExpr::CandidateList & cands = finder.candidates;
    357                         assert( 1 == cands.size() );
    358                         assert( cands.front()->expr );
    359                         crnt.emplace_back( std::move( cands.front() ) );
    360                 }
    361 
    362                 // extract expressions from the assignment candidates to produce a list of assignments
    363                 // that together form a sigle candidate
    364                 std::vector< ast::ptr< ast::Expr > > solved;
    365                 for ( ResolvExpr::CandidateRef & cand : crnt ) {
    366                         solved.emplace_back( cand->expr );
    367                         matcher->combineState( *cand );
    368                 }
    369 
    370                 crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >(
    371                         new ast::TupleAssignExpr(
    372                                 matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) ),
    373                         std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ),
    374                         ResolvExpr::sumCost( crnt ) + matcher->baseCost ) );
    375         }
    376 };
     313                        }
     314                } else {
     315                        // Expand all possible RHS possibilities.
     316                        std::vector< ResolvExpr::CandidateList > rhsCands;
     317                        combos(
     318                                std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) );
     319                        for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) {
     320                                // Multiple assignment:
     321                                ResolvExpr::CandidateList rhs;
     322                                explode( rhsCand, crntFinder.context.symtab, back_inserter( rhs ), true );
     323                                MultipleAssignMatcher matcher( *this, expr->location, lhs, rhs );
     324                                match( matcher );
     325                        }
     326                }
     327        }
     328}
     329
     330void TupleAssignSpotter::match( TupleAssignSpotter::Matcher & matcher ) {
     331        std::vector< ast::ptr< ast::Expr > > newAssigns = matcher.match();
     332
     333        if ( !( matcher.lhs.empty() && matcher.rhs.empty() ) ) {
     334                // If both LHS and RHS are empty than this is the empty tuple
     335                // case, wherein it's okay for newAssigns to be empty. Otherwise,
     336                // return early so that no new candidates are generated.
     337                if ( newAssigns.empty() ) return;
     338        }
     339
     340        ResolvExpr::CandidateList crnt;
     341        // Now resolve new assignments.
     342        for ( const ast::Expr * expr : newAssigns ) {
     343                PRINT(
     344                        std::cerr << "== resolving tuple assign ==" << std::endl;
     345                        std::cerr << expr << std::endl;
     346                )
     347
     348                ResolvExpr::CandidateFinder finder( crntFinder.context, matcher.env );
     349                finder.allowVoid = true;
     350
     351                try {
     352                        finder.find( expr, ResolvExpr::ResolveMode::withAdjustment() );
     353                } catch (...) {
     354                        // No match is not failure, just that this tuple assignment is invalid.
     355                        return;
     356                }
     357
     358                ResolvExpr::CandidateList & cands = finder.candidates;
     359                assert( 1 == cands.size() );
     360                assert( cands.front()->expr );
     361                crnt.emplace_back( std::move( cands.front() ) );
     362        }
     363
     364        // extract expressions from the assignment candidates to produce a list of assignments
     365        // that together form a sigle candidate
     366        std::vector< ast::ptr< ast::Expr > > solved;
     367        for ( ResolvExpr::CandidateRef & cand : crnt ) {
     368                solved.emplace_back( cand->expr );
     369                matcher.combineState( *cand );
     370        }
     371
     372        crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >(
     373                new ast::TupleAssignExpr(
     374                        matcher.location, std::move( solved ), std::move( matcher.tmpDecls ) ),
     375                std::move( matcher.env ), std::move( matcher.open ), std::move( matcher.need ),
     376                ResolvExpr::sumCost( crnt ) + matcher.baseCost ) );
     377}
    377378
    378379} // anonymous namespace
Note: See TracChangeset for help on using the changeset viewer.