Changes in / [42cdd07d:85855b0]


Ignore:
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/lstlang.sty

    r42cdd07d r85855b0  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Fri May 31 14:36:02 2024
    11 %% Update Count     : 44
     10%% Last Modified On : Mon Apr 15 11:28:44 2024
     11%% Update Count     : 43
    1212%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1313
     
    115115        morekeywords={
    116116                alignas, _Alignas, alignof, _Alignof, __alignof, __alignof__, and, asm, __asm, __asm__, _Atomic, __attribute, __attribute__,
    117                 __auto_type, basetypeof, _Bool, bool, catch, catchResume, choose, coerce, corun, cofor, _Complex, __complex, __complex__,
     117                __auto_type, basetypeof, _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

    r42cdd07d r85855b0  
    813813    title       = {The Art of Multiprocessor Programming},
    814814    year        = 2008,
     815    isbn        = {0123705916, 9780123705914},
    815816    publisher   = {Morgan Kaufmann Publishers},
    816817    address     = {San Francisco},
     
    927928    month       = sep,
    928929    year        = 2013,
    929     pages       = {46-53},
     930    pages       = {46--53},
    930931    publisher   = {ACM},
    931932    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},
    943933}
    944934
     
    11161106    publisher   = {ACM},
    11171107    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,
    11281108}
    11291109
     
    43604340    chapter     = {1},
    43614341    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},
    43754342}
    43764343
     
    52045171    journal     = {ACM Trans. Parallel Comput.},
    52055172    issn        = {2329-4949},
     5173    url         = {https://doi.org/10.1145/3584696},
     5174    doi         = {10.1145/3584696},
    52065175    articleno   = 11,
    52075176    numpages    = 23,
     
    78007769}
    78017770
    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 
    78127771@inproceedings{Leissa14,
    78137772    title       = {{S}ierra: a {SIMD} extension for {C}++},
     
    87028661}
    87038662
    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 
    87148663@article{Leroy00,
    87158664    keywords    = {type-systems, exceptions},
     
    88038752    title       = {Understanding Control Flow: Concurrent Programming using $\mu${C}{\kern-.1em\hbox{\large\texttt{+\kern-.25em+}}}},
    88048753    publisher   = {Springer},
    8805     address     = {Cham, Switzerland},
     8754    address     = {Switzerland},
    88068755    year        = 2016,
    88078756}
  • doc/proposals/modules.md

    r42cdd07d r85855b0  
    55======================
    66
    7 In 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 
    9 Note 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 
    11 In 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,
     7Modules 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.
    128
    139Uses of Modules
    1410---------------
    15 This section covers the features module system to allow for the separatation of code across modules and why
     11The most straight forward purpose of modules is to enable separate compilation.
     12This in turn reduces recompilation, by isolating changes, and parallel compilation, but making modules independent.
    1613
    17 Modules 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.
     14An 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.
    1815
    19 []
    20 
    21 If 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 
    25 Accessablity 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 
    27 In 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.
     16Modules 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.
    2817
    2918C Comparisons
     
    9180Second, this does nothing to solve the oversized header issue. It does not reduce any requirements on what includes need to be use.
    9281
    93 Alternate Solutions
    94 -------------------
    95 There are other ways C's modules could be improved in Cforall.
    96 
    97 Explicit Module Blocks
    98 ......................
    99 Instead 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 
    109 The 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 
    111 Compiled Headers
    112 ................
    113 Most 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 
    115 This 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 
    117 There 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.
    11882
    11983##########################################################################################
     
    12286----'
    12387
    124 Programming 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.
     88Programming 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.
    12589Separate 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.
    12690The compiler output is placed in another set of files for execution loading or further processing.
     
    13397In 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.
    13498Without embedded file-links, dynamic embedding using #include/import is necessary to compose all the program components necessary for a compilation.
    135 
    136 inlining?
    13799
    138100I see two separate issues with respect to program structuring for controlling visibility and initializing a program.
  • src/InitTweak/GenInit.cpp

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

    r42cdd07d r85855b0  
    241241        ResolvExpr::CandidateFinder & crntFinder;
    242242        std::string fname;
     243        std::unique_ptr< Matcher > matcher;
    243244
    244245public:
    245246        TupleAssignSpotter( ResolvExpr::CandidateFinder & f )
    246         : crntFinder( f ), fname() {}
    247 
    248         /// Find left- and right-hand-sides for mass or multiple assignment.
     247        : crntFinder( f ), fname(), matcher() {}
     248
     249        // Find left- and right-hand-sides for mass or multiple assignment.
    249250        void spot(
    250251                const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
    251         );
    252         /// Wrapper around matcher.match.
    253         void match( Matcher & matcher );
     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 ) );
     273                                }
     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        }
    254376};
    255 
    256 void 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 );
    312                                 }
    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 
    330 void 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 }
    378377
    379378} // anonymous namespace
Note: See TracChangeset for help on using the changeset viewer.