Changeset 7770cc8 for src


Ignore:
Timestamp:
Nov 24, 2021, 9:47:56 PM (4 years ago)
Author:
Michael Brooks <mlbrooks@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
Children:
5235d49
Parents:
94647b0b (diff), 3cc1111 (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

Location:
src
Files:
17 added
37 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r94647b0b r7770cc8  
    10411041
    10421042        const ast::Expr * visit( const ast::StmtExpr * node ) override final {
    1043                 auto stmts = node->stmts;
    1044                 // disable sharing between multiple StmtExprs explicitly.
    1045                 // this should no longer be true.
    1046 
    10471043                auto rslt = new StmtExpr(
    1048                         get<CompoundStmt>().accept1(stmts)
     1044                        get<CompoundStmt>().accept1(node->stmts)
    10491045                );
    10501046
    10511047                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
    10521048                rslt->dtors       = get<Expression>().acceptL(node->dtors);
    1053                 if (node->resultExpr) {
    1054                         // this MUST be found by children visit
    1055                         rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr));
    1056                 }
     1049
     1050                // is this even used after convert?
     1051                //if (tmp->resultExpr) {
     1052                //      // this MUST be found by children visit
     1053                //      rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(tmp->resultExpr));
     1054                //}
    10571055
    10581056                auto expr = visitBaseExpr( node, rslt );
     
    14461444
    14471445std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit ) {
     1446        // Copy values from the global store to the local static variables.
     1447        ast::sizeType = translationUnit.global.sizeType;
     1448        ast::dereferenceOperator = translationUnit.global.dereference;
     1449        ast::dtorStruct = translationUnit.global.dtorStruct;
     1450        ast::dtorStructDestroy = translationUnit.global.dtorDestroy;
     1451
    14481452        ConverterNewToOld c;
    14491453        std::list< Declaration * > decls;
  • src/AST/Copy.hpp

    r94647b0b r7770cc8  
    1010// Created On       : Wed Jul 10 16:13:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 19 16:43:00 2020
    13 // Update Count     : 1
     12// Last Modified On : Thr Nov 11  9:22:00 2021
     13// Update Count     : 2
    1414//
    1515
    1616#pragma once
    1717
    18 #include "Decl.hpp"
    19 #include "Expr.hpp"
    20 #include "Pass.hpp"
    21 #include "Stmt.hpp"
    22 #include "Type.hpp"
    23 #include <unordered_set>
    24 #include <unordered_map>
     18#include "Node.hpp"
     19#include <cassert>
    2520
    2621namespace ast {
     
    4338 */
    4439
    45 class DeepCopyCore {
    46         std::unordered_map< const Node *, const Node * > nodeCache;
    47         std::unordered_set< readonly<Node> * > readonlyCache;
    48 
    49         template<typename node_t>
    50         void readonlyInsert( const readonly<node_t> * ptrptr ) {
    51                 readonlyCache.insert( (readonly<Node> *) ptrptr );
    52         }
    53 
    54 public:
    55         template<typename node_t>
    56         const node_t * previsit( const node_t * node ) {
    57                 const node_t * copy = shallowCopy( node );
    58                 nodeCache.insert( std::make_pair( node, copy ) );
    59                 return copy;
    60         }
    61 
    62         void postvisit( const AggregateDecl * node ) {
    63                 readonlyInsert( &node->parent );
    64         }
    65 
    66         void postvisit( const StructInstType * node ) {
    67                 readonlyInsert( &node->base );
    68         }
    69 
    70         void postvisit( const UnionInstType * node ) {
    71                 readonlyInsert( &node->base );
    72         }
    73 
    74         void postvisit( const EnumInstType * node ) {
    75                 readonlyInsert( &node->base );
    76         }
    77 
    78         void postvisit( const TraitInstType * node ) {
    79                 readonlyInsert( &node->base );
    80         }
    81 
    82         void postvisit( const TypeInstType * node ) {
    83                 readonlyInsert( &node->base );
    84         }
    85 
    86         void postvisit( const ImplicitCtorDtorStmt * node ) {
    87                 readonlyInsert( (const readonly<Stmt> *) &node->callStmt );
    88         }
    89 
    90         void postvisit( const MemberExpr * node ) {
    91                 readonlyInsert( &node->member );
    92         }
    93 
    94         void postvisit( const VariableExpr * node ) {
    95                 readonlyInsert( &node->var );
    96         }
    97 
    98         void postvisit( const OffsetofExpr * node ) {
    99                 readonlyInsert( &node->member );
    100         }
    101 
    102         void postvisit( const DeletedExpr * node ) {
    103                 readonlyInsert( &node->deleteStmt );
    104         }
    105 
    106         void readonlyUpdates() {
    107                 for ( readonly<Node> * ptr : readonlyCache ) {
    108                         auto it = nodeCache.find( ptr->get() );
    109                         if ( nodeCache.end() != it ) {
    110                                 *ptr = it->second;
    111                         }
    112                 }
    113         }
    114 };
    115 
     40// Implementations:
    11641template<typename node_t>
    11742node_t * shallowCopy( const node_t * localRoot ) {
     
    12146template<typename node_t>
    12247node_t * deepCopy( const node_t * localRoot ) {
    123         Pass< DeepCopyCore > dc;
    124         node_t const * newRoot = localRoot->accept( dc );
    125         dc.core.readonlyUpdates();
    126         return const_cast< node_t * >( newRoot );
     48        return strict_dynamic_cast<node_t *>( deepCopy<Node>( localRoot ) );
    12749}
     50
     51template<>
     52Node * deepCopy<Node>( const Node * localRoot );
    12853
    12954}
  • src/AST/Decl.hpp

    r94647b0b r7770cc8  
    131131        // declared type, derived from parameter declarations
    132132        ptr<FunctionType> type;
     133        /// Null for the forward declaration of a function.
    133134        ptr<CompoundStmt> stmts;
    134135        std::vector< ptr<Expr> > withExprs;
     
    269270        : AggregateDecl( loc, name, std::move(attrs), linkage ), kind( kind ) {}
    270271
    271         bool is_coroutine() { return kind == Coroutine; }
    272         bool is_generator() { return kind == Generator; }
    273         bool is_monitor  () { return kind == Monitor  ; }
    274         bool is_thread   () { return kind == Thread   ; }
     272        bool is_coroutine() const { return kind == Coroutine; }
     273        bool is_generator() const { return kind == Generator; }
     274        bool is_monitor  () const { return kind == Monitor  ; }
     275        bool is_thread   () const { return kind == Thread   ; }
    275276
    276277        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Init.hpp

    r94647b0b r7770cc8  
    9898        const_iterator begin() const { return initializers.begin(); }
    9999        const_iterator end() const { return initializers.end(); }
     100        size_t size() const { return initializers.size(); }
    100101
    101102        const Init * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Pass.hpp

    r94647b0b r7770cc8  
    109109        static auto read( node_type const * node, Args&&... args ) {
    110110                Pass<core_t> visitor( std::forward<Args>( args )... );
    111                 node_type const * temp = node->accept( visitor );
     111                auto const * temp = node->accept( visitor );
    112112                assert( temp == node );
    113113                return visitor.get_result();
     
    124124        static auto read( node_type const * node ) {
    125125                Pass<core_t> visitor;
    126                 node_type const * temp = node->accept( visitor );
     126                auto const * temp = node->accept( visitor );
    127127                assert( temp == node );
    128128                return visitor.get_result();
     
    348348
    349349        /// When this node is finished being visited, restore the value of a variable
     350        /// You may assign to the return value to set the new value in the same statement.
    350351        template< typename T >
    351         void GuardValue( T& val ) {
     352        T& GuardValue( T& val ) {
    352353                at_cleanup( [ val ]( void * newVal ) {
    353354                        * static_cast< T * >( newVal ) = val;
    354355                }, static_cast< void * >( & val ) );
     356                return val;
    355357        }
    356358
     
    394396};
    395397
     398/// Used to get a pointer to the wrapping TranslationUnit.
     399struct WithConstTranslationUnit {
     400        const TranslationUnit * translationUnit = nullptr;
     401
     402        const TranslationUnit & transUnit() const {
     403                assertf( translationUnit, "WithConstTranslationUnit not set-up." );
     404                return *translationUnit;
     405        }
     406};
     407
    396408}
    397409
  • src/AST/Pass.impl.hpp

    r94647b0b r7770cc8  
    420420template< typename core_t >
    421421inline void ast::accept_all( ast::TranslationUnit & unit, ast::Pass< core_t > & visitor ) {
    422         return ast::accept_all( unit.decls, visitor );
     422        if ( auto ptr = __pass::translation_unit::get_cptr( visitor.core, 0 ) ) {
     423                ValueGuard<const TranslationUnit *> guard( *ptr );
     424                *ptr = &unit;
     425                return ast::accept_all( unit.decls, visitor );
     426        } else {
     427                return ast::accept_all( unit.decls, visitor );
     428        }
    423429}
    424430
  • src/AST/Pass.proto.hpp

    r94647b0b r7770cc8  
    426426        } // namespace forall
    427427
     428        // For passes that need access to the global context. Sreaches `translationUnit`
     429        namespace translation_unit {
     430                template<typename core_t>
     431                static inline auto get_cptr( core_t & core, int )
     432                                -> decltype( &core.translationUnit ) {
     433                        return &core.translationUnit;
     434                }
     435
     436                template<typename core_t>
     437                static inline const TranslationUnit ** get_cptr( core_t &, long ) {
     438                        return nullptr;
     439                }
     440        }
     441
    428442        template<typename core_t>
    429443        static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) {
  • src/AST/Stmt.hpp

    r94647b0b r7770cc8  
    175175class CaseStmt final : public Stmt {
    176176public:
     177        /// Null for the default label.
    177178        ptr<Expr> cond;
    178179        std::vector<ptr<Stmt>> stmts;
  • src/AST/TranslationUnit.hpp

    r94647b0b r7770cc8  
    2626        std::list< ptr< Decl > > decls;
    2727
    28         struct Globals {
     28        struct Global {
    2929                std::map< UniqueId, Decl * > idMap;
    3030
    31                 const Type * sizeType;
     31                ptr<Type> sizeType;
    3232                const FunctionDecl * dereference;
    3333                const StructDecl * dtorStruct;
  • src/AST/module.mk

    r94647b0b r7770cc8  
    2424        AST/Convert.cpp \
    2525        AST/Convert.hpp \
     26        AST/Copy.cpp \
    2627        AST/Copy.hpp \
    2728        AST/CVQualifiers.hpp \
  • src/AST/porting.md

    r94647b0b r7770cc8  
    9898        * `Initializer` => `ast::Init`
    9999    * `Statement` => `ast::Stmt`
     100    * `ReferenceToType` => `ast::BaseInstType`
    100101        * any field names should follow a similar renaming
    101102  * because they don't really belong to `Type` (and for consistency with `Linkage::Spec`):
  • src/CodeGen/FixMain.cc

    r94647b0b r7770cc8  
    2222#include <string>                  // for operator<<
    2323
     24#include "AST/Decl.hpp"
     25#include "AST/Type.hpp"
     26#include "Common/PassVisitor.h"
    2427#include "Common/SemanticError.h"  // for SemanticError
    2528#include "CodeGen/GenType.h"       // for GenType
     
    2932
    3033namespace CodeGen {
     34
     35namespace {
     36
     37struct FindMainCore {
     38        FunctionDecl * main_signature = nullptr;
     39
     40        void previsit( FunctionDecl * decl ) {
     41                if ( FixMain::isMain( decl ) ) {
     42                        if ( main_signature ) {
     43                                SemanticError( decl, "Multiple definition of main routine\n" );
     44                        }
     45                        main_signature = decl;
     46                }
     47        }
     48};
     49
     50}
     51
    3152        bool FixMain::replace_main = false;
    32         std::unique_ptr<FunctionDecl> FixMain::main_signature = nullptr;
    3353
    3454        template<typename container>
     
    3757        }
    3858
    39         void FixMain::registerMain(FunctionDecl* functionDecl)
    40         {
    41                 if(main_signature) {
    42                         SemanticError(functionDecl, "Multiple definition of main routine\n");
    43                 }
    44                 main_signature.reset( functionDecl->clone() );
    45         }
     59        void FixMain::fix( std::list< Declaration * > & translationUnit,
     60                        std::ostream &os, const char* bootloader_filename ) {
     61                PassVisitor< FindMainCore > main_finder;
     62                acceptAll( translationUnit, main_finder );
     63                FunctionDecl * main_signature = main_finder.pass.main_signature;
    4664
    47         void FixMain::fix(std::ostream &os, const char* bootloader_filename) {
    4865                if( main_signature ) {
    4966                        os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return ";
    50                         main_signature->mangleName = SymTab::Mangler::mangle(main_signature.get());
     67                        main_signature->mangleName = SymTab::Mangler::mangle(main_signature);
    5168
    5269                        os << main_signature->get_scopedMangleName() << "(";
     
    6582                }
    6683        }
     84
     85namespace {
     86
     87ObjectDecl * signedIntObj() {
     88        return new ObjectDecl(
     89                "", Type::StorageClasses(), LinkageSpec::Cforall, 0,
     90                new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr );
     91}
     92
     93ObjectDecl * charStarObj() {
     94        return new ObjectDecl(
     95                "", Type::StorageClasses(), LinkageSpec::Cforall, 0,
     96                new PointerType( Type::Qualifiers(),
     97                        new PointerType( Type::Qualifiers(),
     98                                new BasicType( Type::Qualifiers(), BasicType::Char ) ) ),
     99                nullptr );
     100}
     101
     102std::string create_mangled_main_function_name( FunctionType * function_type ) {
     103        std::unique_ptr<FunctionDecl> decl( new FunctionDecl(
     104                "main", Type::StorageClasses(), LinkageSpec::Cforall,
     105                function_type, nullptr ) );
     106        return SymTab::Mangler::mangle( decl.get() );
     107}
     108
     109std::string mangled_0_argument_main() {
     110        FunctionType* main_type = new FunctionType( Type::Qualifiers(), true );
     111        main_type->get_returnVals().push_back( signedIntObj() );
     112        return create_mangled_main_function_name( main_type );
     113}
     114
     115std::string mangled_2_argument_main() {
     116        FunctionType* main_type = new FunctionType( Type::Qualifiers(), false );
     117        main_type->get_returnVals().push_back( signedIntObj() );
     118        main_type->get_parameters().push_back( signedIntObj() );
     119        main_type->get_parameters().push_back( charStarObj() );
     120        return create_mangled_main_function_name( main_type );
     121}
     122
     123bool is_main( const std::string & mangled_name ) {
     124        // This breaks if you move it out of the function.
     125        static const std::string mangled_mains[] = {
     126                mangled_0_argument_main(),
     127                mangled_2_argument_main(),
     128                //mangled_3_argument_main(),
     129        };
     130
     131        for ( auto main_name : mangled_mains ) {
     132                if ( main_name == mangled_name ) return true;
     133        }
     134        return false;
     135}
     136
     137} // namespace
     138
     139bool FixMain::isMain( FunctionDecl * decl ) {
     140        if ( std::string("main") != decl->name ) {
     141                return false;
     142        }
     143        return is_main( SymTab::Mangler::mangle( decl, true, true ) );
     144}
     145
     146bool FixMain::isMain( const ast::FunctionDecl * decl ) {
     147        if ( std::string("main") != decl->name ) {
     148                return false;
     149        }
     150        return is_main( Mangle::mangle( decl, Mangle::Type ) );
     151}
     152
    67153};
  • src/CodeGen/FixMain.h

    r94647b0b r7770cc8  
    99// Author           : Thierry Delisle
    1010// Created On       : Thr Jan 12 14:11:09 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Feb 16 03:24:32 2020
    13 // Update Count     : 5
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct 29 16:20:00 2021
     13// Update Count     : 8
    1414//
    1515
     
    1818#include <iosfwd>
    1919#include <memory>
     20#include <list>
    2021
    2122#include "SynTree/LinkageSpec.h"
    2223
     24class Declaration;
    2325class FunctionDecl;
     26namespace ast {
     27        class FunctionDecl;
     28}
    2429
    2530namespace CodeGen {
    26         class FixMain {
    27           public :
    28                 static inline LinkageSpec::Spec mainLinkage() {
    29                         return replace_main ? LinkageSpec::Cforall : LinkageSpec::C;
    30                 }
    31                
    32                 static inline void setReplaceMain(bool val) {
    33                         replace_main = val;
    34                 }
    3531
    36                 static void registerMain(FunctionDecl* val);
     32class FixMain {
     33public :
     34        static inline LinkageSpec::Spec mainLinkage() {
     35                return replace_main ? LinkageSpec::Cforall : LinkageSpec::C;
     36        }
    3737
    38                 static void fix(std::ostream &os, const char* bootloader_filename);
     38        static inline void setReplaceMain(bool val) {
     39                replace_main = val;
     40        }
    3941
    40           private:
    41                 static bool replace_main;
    42                 static std::unique_ptr<FunctionDecl> main_signature;
    43         };
     42        static bool isMain(FunctionDecl* decl);
     43        static bool isMain(const ast::FunctionDecl * decl);
     44
     45        static void fix( std::list< Declaration * > & decls,
     46                        std::ostream &os, const char* bootloader_filename );
     47
     48private:
     49        static bool replace_main;
     50};
     51
    4452} // namespace CodeGen
  • src/CodeGen/FixNames.cc

    r94647b0b r7770cc8  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:39:14 2019
    13 // Update Count     : 21
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct 29 15:49:00 2021
     13// Update Count     : 23
    1414//
    1515
     
    1919#include <string>                  // for string, operator!=, operator==
    2020
     21#include "AST/Chain.hpp"
     22#include "AST/Expr.hpp"
     23#include "AST/Pass.hpp"
    2124#include "Common/PassVisitor.h"
    2225#include "Common/SemanticError.h"  // for SemanticError
     
    4649        };
    4750
    48         std::string mangle_main() {
    49                 FunctionType* main_type;
    50                 std::unique_ptr<FunctionDecl> mainDecl { new FunctionDecl( "main", Type::StorageClasses(), LinkageSpec::Cforall,
    51                                                                                                                                    main_type = new FunctionType( Type::Qualifiers(), true ), nullptr )
    52                                 };
    53                 main_type->get_returnVals().push_back(
    54                         new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr )
    55                 );
    56 
    57                 auto && name = SymTab::Mangler::mangle( mainDecl.get() );
    58                 // std::cerr << name << std::endl;
    59                 return std::move(name);
    60         }
    61         std::string mangle_main_args() {
    62                 FunctionType* main_type;
    63                 std::unique_ptr<FunctionDecl> mainDecl { new FunctionDecl( "main", Type::StorageClasses(), LinkageSpec::Cforall,
    64                                                                                                                                    main_type = new FunctionType( Type::Qualifiers(), false ), nullptr )
    65                                 };
    66                 main_type->get_returnVals().push_back(
    67                         new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr )
    68                 );
    69 
    70                 main_type->get_parameters().push_back(
    71                         new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr )
    72                 );
    73 
    74                 main_type->get_parameters().push_back(
    75                         new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0,
    76                         new PointerType( Type::Qualifiers(), new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Char ) ) ),
    77                         nullptr )
    78                 );
    79 
    80                 auto&& name = SymTab::Mangler::mangle( mainDecl.get() );
    81                 // std::cerr << name << std::endl;
    82                 return std::move(name);
    83         }
    84 
    85         bool is_main(const std::string& name) {
    86                 static std::string mains[] = {
    87                         mangle_main(),
    88                         mangle_main_args()
    89                 };
    90 
    91                 for(const auto& m : mains) {
    92                         if( name == m ) return true;
    93                 }
    94                 return false;
    95         }
    96 
    9751        void fixNames( std::list< Declaration* > & translationUnit ) {
    9852                PassVisitor<FixNames> fixer;
     
    11872                fixDWT( functionDecl );
    11973
    120                 if(is_main( SymTab::Mangler::mangle(functionDecl, true, true) )) {
     74                if ( FixMain::isMain( functionDecl ) ) {
    12175                        int nargs = functionDecl->get_functionType()->get_parameters().size();
    12276                        if( !(nargs == 0 || nargs == 2 || nargs == 3) ) {
     
    12478                        }
    12579                        functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) );
    126                         CodeGen::FixMain::registerMain( functionDecl );
    12780                }
    12881        }
     
    13285                GuardAction( [this](){ scopeLevel--; } );
    13386        }
     87
     88/// Does work with the main function and scopeLevels.
     89class FixNames_new : public ast::WithGuards {
     90        int scopeLevel = 1;
     91
     92        bool shouldSetScopeLevel( const ast::DeclWithType * dwt ) {
     93                return !dwt->name.empty() && dwt->linkage.is_mangled
     94                        && dwt->scopeLevel != scopeLevel;
     95        }
     96public:
     97        const ast::ObjectDecl *postvisit( const ast::ObjectDecl *objectDecl ) {
     98                if ( shouldSetScopeLevel( objectDecl ) ) {
     99                        return ast::mutate_field( objectDecl, &ast::ObjectDecl::scopeLevel, scopeLevel );
     100                }
     101                return objectDecl;
     102        }
     103
     104        const ast::FunctionDecl *postvisit( const ast::FunctionDecl *functionDecl ) {
     105                // This store is used to ensure a maximum of one call to mutate.
     106                ast::FunctionDecl * mutDecl = nullptr;
     107
     108                if ( shouldSetScopeLevel( functionDecl ) ) {
     109                        mutDecl = ast::mutate( functionDecl );
     110                        mutDecl->scopeLevel = scopeLevel;
     111                }
     112
     113                if ( FixMain::isMain( functionDecl ) ) {
     114                        if ( !mutDecl ) { mutDecl = ast::mutate( functionDecl ); }
     115
     116                        int nargs = mutDecl->params.size();
     117                        if ( 0 != nargs && 2 != nargs && 3 != nargs ) {
     118                                SemanticError( functionDecl, "Main expected to have 0, 2 or 3 arguments\n" );
     119                        }
     120                        ast::chain_mutate( mutDecl->stmts )->kids.push_back(
     121                                new ast::ReturnStmt(
     122                                        mutDecl->location,
     123                                        ast::ConstantExpr::from_int( mutDecl->location, 0 )
     124                                )
     125                        );
     126                }
     127                return mutDecl ? mutDecl : functionDecl;
     128        }
     129
     130        void previsit( const ast::CompoundStmt * ) {
     131                GuardValue( scopeLevel ) += 1;
     132        }
     133};
     134
     135void fixNames( ast::TranslationUnit & translationUnit ) {
     136        ast::Pass<FixNames_new>::run( translationUnit );
     137}
     138
    134139} // namespace CodeGen
    135140
  • src/CodeGen/FixNames.h

    r94647b0b r7770cc8  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 22:17:33 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct 26 13:47:00 2021
     13// Update Count     : 4
    1414//
    1515
     
    1919
    2020class Declaration;
     21namespace ast {
     22        struct TranslationUnit;
     23}
    2124
    2225namespace CodeGen {
    2326        /// mangles object and function names
    2427        void fixNames( std::list< Declaration* > & translationUnit );
     28        void fixNames( ast::TranslationUnit & translationUnit );
    2529} // namespace CodeGen
    2630
  • src/CodeTools/DeclStats.cc

    r94647b0b r7770cc8  
    156156                /// number of counting bins for linkages
    157157                static const unsigned n_named_specs = 8;
    158                 /// map from total number of specs to bins
    159                 static const unsigned ind_for_linkage[16];
     158                /// Mapping function from linkage to bin.
     159                static unsigned linkage_index( LinkageSpec::Spec spec ) {
     160                        switch ( spec ) {
     161                        case LinkageSpec::Intrinsic:  return 0;
     162                        case LinkageSpec::C:          return 1;
     163                        case LinkageSpec::Cforall:    return 2;
     164                        case LinkageSpec::AutoGen:    return 3;
     165                        case LinkageSpec::Compiler:   return 4;
     166                        case LinkageSpec::BuiltinCFA: return 5;
     167                        case LinkageSpec::BuiltinC:   return 6;
     168                        default:                      return 7;
     169                        }
     170                }
    160171
    161172                Stats for_linkage[n_named_specs];            ///< Stores separate stats per linkage
     
    366377                        const std::string& mangleName = decl->get_mangleName().empty() ? decl->name : decl->get_mangleName();
    367378                        if ( seen_names.insert( mangleName ).second ) {
    368                                 Stats& stats = for_linkage[ ind_for_linkage[ decl->linkage ] ];
     379                                Stats& stats = for_linkage[ linkage_index( decl->linkage ) ];
    369380
    370381                                ++stats.n_decls;
     
    527538        };
    528539
    529         const unsigned DeclStats::ind_for_linkage[]
    530                 = { 7, 7, 2, 1,   7, 7, 7, 3,   4, 7, 6, 5,   7, 7, 7, 0 };
    531 
    532540        void printDeclStats( std::list< Declaration * > &translationUnit ) {
    533541                PassVisitor<DeclStats> stats;
  • src/Common/module.mk

    r94647b0b r7770cc8  
    2222      Common/CompilerError.h \
    2323      Common/Debug.h \
     24      Common/DeclStats.hpp \
     25      Common/DeclStats.cpp \
    2426      Common/ErrorObjects.h \
    2527      Common/Eval.cc \
     
    3335      Common/PassVisitor.proto.h \
    3436      Common/PersistentMap.h \
     37      Common/ResolvProtoDump.hpp \
     38      Common/ResolvProtoDump.cpp \
    3539      Common/ScopedMap.h \
    3640      Common/SemanticError.cc \
  • src/Concurrency/Keywords.cc

    r94647b0b r7770cc8  
    979979                        // If this is the destructor for a monitor it must be mutex
    980980                        if(isDtor) {
     981                                // This reflects MutexKeyword::validate, except does not produce an error.
    981982                                Type* ty = decl->get_functionType()->get_parameters().front()->get_type();
    982983
  • src/ControlStruct/ExceptTranslate.cc

    r94647b0b r7770cc8  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ExceptVisitor.cc --
     7// ExceptTranslate.cc -- Conversion of exception control flow structures.
    88//
    99// Author           : Andrew Beach
  • src/ControlStruct/ExceptTranslate.h

    r94647b0b r7770cc8  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ExceptTranslate.h --
     7// ExceptTranslate.h -- Conversion of exception control flow structures.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Tus Jun 06 10:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus May 19 11:47:00 2020
    13 // Update Count     : 5
     12// Last Modified On : Mon Nov  8 11:43:00 2020
     13// Update Count     : 6
    1414//
    1515
     
    1919
    2020class Declaration;
     21namespace ast {
     22        class TranslationUnit;
     23}
    2124
    2225namespace ControlStruct {
    2326        void translateThrows( std::list< Declaration *> & translationUnit );
     27        void translateThrows( ast::TranslationUnit & transUnit );
    2428        /* Replaces all throw & throwResume statements with function calls.
    2529         * These still need to be resolved, so call this before the reslover.
  • src/ControlStruct/LabelGenerator.cc

    r94647b0b r7770cc8  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 11 22:23:20 2019
    13 // Update Count     : 15
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Nov  8 10:18:00 2021
     13// Update Count     : 17
    1414//
    1515
     
    1919
    2020#include "LabelGenerator.h"
     21
     22#include "AST/Attribute.hpp"
     23#include "AST/Label.hpp"
     24#include "AST/Stmt.hpp"
    2125#include "SynTree/Attribute.h"  // for Attribute
    2226#include "SynTree/Label.h"      // for Label, operator<<
     
    2428
    2529namespace ControlStruct {
    26         LabelGenerator * LabelGenerator::labelGenerator = 0;
     30
     31int LabelGenerator::current = 0;
     32LabelGenerator * LabelGenerator::labelGenerator = nullptr;
    2733
    2834        LabelGenerator * LabelGenerator::getGenerator() {
     
    4349                return l;
    4450        }
     51
     52ast::Label LabelGenerator::newLabel(
     53                const std::string & suffix, const ast::Stmt * stmt ) {
     54        assert( stmt );
     55
     56        std::ostringstream os;
     57        os << "__L" << current++ << "__" << suffix;
     58        if ( stmt && !stmt->labels.empty() ) {
     59                os << "_" << stmt->labels.front() << "__";
     60        }
     61        ast::Label ret_label( stmt->location, os.str() );
     62        ret_label.attributes.push_back( new ast::Attribute( "unused" ) );
     63        return ret_label;
     64}
     65
    4566} // namespace ControlStruct
    4667
  • src/ControlStruct/LabelGenerator.h

    r94647b0b r7770cc8  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:20:14 2017
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Nov  8 10:16:00 2021
     13// Update Count     : 8
    1414//
    1515
     
    2121
    2222class Statement;
     23namespace ast {
     24        class Stmt;
     25        class Label;
     26}
    2327
    2428namespace ControlStruct {
    25         class LabelGenerator {
    26           public:
    27                 static LabelGenerator *getGenerator();
    28                 Label newLabel(std::string suffix, Statement * stmt = nullptr);
    29                 void reset() { current = 0; }
    30                 void rewind() { current--; }
    31           protected:
    32                 LabelGenerator(): current(0) {}
    33           private:
    34                 int current;
    35                 static LabelGenerator *labelGenerator;
    36         };
     29
     30class LabelGenerator {
     31        static int current;
     32        static LabelGenerator *labelGenerator;
     33protected:
     34        LabelGenerator() {}
     35public:
     36        static LabelGenerator *getGenerator();
     37        static Label newLabel(std::string suffix, Statement * stmt = nullptr);
     38        static ast::Label newLabel( const std::string&, const ast::Stmt * );
     39        static void reset() { current = 0; }
     40        static void rewind() { current--; }
     41};
     42
    3743} // namespace ControlStruct
    3844
  • src/ControlStruct/module.mk

    r94647b0b r7770cc8  
    1818        ControlStruct/ExceptDecl.cc \
    1919        ControlStruct/ExceptDecl.h \
     20        ControlStruct/FixLabels.cpp \
     21        ControlStruct/FixLabels.hpp \
    2022        ControlStruct/ForExprMutator.cc \
    2123        ControlStruct/ForExprMutator.h \
     
    2628        ControlStruct/MLEMutator.cc \
    2729        ControlStruct/MLEMutator.h \
     30        ControlStruct/MultiLevelExit.cpp \
     31        ControlStruct/MultiLevelExit.hpp \
    2832        ControlStruct/Mutate.cc \
    2933        ControlStruct/Mutate.h
    3034
    31 SRC += $(SRC_CONTROLSTRUCT) ControlStruct/ExceptTranslate.cc ControlStruct/ExceptTranslate.h
     35SRC += $(SRC_CONTROLSTRUCT) \
     36        ControlStruct/ExceptTranslateNew.cpp \
     37        ControlStruct/ExceptTranslate.cc \
     38        ControlStruct/ExceptTranslate.h
     39
    3240SRCDEMANGLE += $(SRC_CONTROLSTRUCT)
    3341
  • src/InitTweak/FixInitNew.cpp

    r94647b0b r7770cc8  
    591591                // need to add __Destructor for _tmp_cp variables as well
    592592
    593                 assertf( ast::dtorStruct && ast::dtorStruct->members.size() == 2, "Destructor generation requires __Destructor definition." );
     593                assertf( ast::dtorStruct, "Destructor generation requires __Destructor definition." );
     594                assertf( ast::dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );
    594595                assertf( ast::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );
    595596
     
    12161217
    12171218                                                        static UniqueName memberDtorNamer = { "__memberDtor" };
    1218                                                         assertf( Validate::dtorStruct, "builtin __Destructor not found." );
    1219                                                         assertf( Validate::dtorStructDestroy, "builtin __destroy_Destructor not found." );
     1219                                                        assertf( ast::dtorStruct, "builtin __Destructor not found." );
     1220                                                        assertf( ast::dtorStructDestroy, "builtin __destroy_Destructor not found." );
    12201221
    12211222                                                        ast::Expr * thisExpr = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, thisParam ) ), new ast::PointerType( new ast::VoidType(), ast::CV::Qualifiers() ) );
  • src/InitTweak/GenInit.cc

    r94647b0b r7770cc8  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:15:10 2019
    13 // Update Count     : 184
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Oct 25 13:53:00 2021
     13// Update Count     : 186
    1414//
    1515#include "GenInit.h"
     
    2424#include "AST/Decl.hpp"
    2525#include "AST/Init.hpp"
     26#include "AST/Pass.hpp"
    2627#include "AST/Node.hpp"
    2728#include "AST/Stmt.hpp"
     
    294295        }
    295296
     297namespace {
     298
     299#       warning Remove the _New suffix after the conversion is complete.
     300        struct HoistArrayDimension_NoResolve_New final :
     301                        public ast::WithDeclsToAdd<>, public ast::WithShortCircuiting,
     302                        public ast::WithGuards, public ast::WithConstTranslationUnit,
     303                        public ast::WithVisitorRef<HoistArrayDimension_NoResolve_New> {
     304                void previsit( const ast::ObjectDecl * decl );
     305                const ast::DeclWithType * postvisit( const ast::ObjectDecl * decl );
     306                // Do not look for objects inside there declarations (and type).
     307                void previsit( const ast::AggregateDecl * ) { visit_children = false; }
     308                void previsit( const ast::NamedTypeDecl * ) { visit_children = false; }
     309                void previsit( const ast::FunctionType * ) { visit_children = false; }
     310
     311                const ast::Type * hoist( const ast::Type * type );
     312
     313                ast::Storage::Classes storageClasses;
     314        };
     315
     316        void HoistArrayDimension_NoResolve_New::previsit(
     317                        const ast::ObjectDecl * decl ) {
     318                GuardValue( storageClasses ) = decl->storage;
     319        }
     320
     321        const ast::DeclWithType * HoistArrayDimension_NoResolve_New::postvisit(
     322                        const ast::ObjectDecl * objectDecl ) {
     323                return mutate_field( objectDecl, &ast::ObjectDecl::type,
     324                                hoist( objectDecl->type ) );
     325        }
     326
     327        const ast::Type * HoistArrayDimension_NoResolve_New::hoist(
     328                        const ast::Type * type ) {
     329                static UniqueName dimensionName( "_array_dim" );
     330
     331                if ( !isInFunction() || storageClasses.is_static ) {
     332                        return type;
     333                }
     334
     335                if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
     336                        if ( nullptr == arrayType->dimension ) {
     337                                return type;
     338                        }
     339
     340                        if ( !Tuples::maybeImpure( arrayType->dimension ) ) {
     341                                return type;
     342                        }
     343
     344                        ast::ptr<ast::Type> dimType = transUnit().global.sizeType;
     345                        assert( dimType );
     346                        add_qualifiers( dimType, ast::CV::Qualifiers( ast::CV::Const ) );
     347
     348                        ast::ObjectDecl * arrayDimension = new ast::ObjectDecl(
     349                                arrayType->dimension->location,
     350                                dimensionName.newName(),
     351                                dimType,
     352                                new ast::SingleInit(
     353                                        arrayType->dimension->location,
     354                                        arrayType->dimension
     355                                )
     356                        );
     357
     358                        ast::ArrayType * mutType = ast::mutate( arrayType );
     359                        mutType->dimension = new ast::VariableExpr(
     360                                        arrayDimension->location, arrayDimension );
     361                        declsToAddBefore.push_back( arrayDimension );
     362
     363                        mutType->base = hoist( mutType->base );
     364                        return mutType;
     365                }
     366                return type;
     367        }
     368
     369        struct ReturnFixer_New final :
     370                        public ast::WithStmtsToAdd<>, ast::WithGuards {
     371                void previsit( const ast::FunctionDecl * decl );
     372                const ast::ReturnStmt * previsit( const ast::ReturnStmt * stmt );
     373        private:
     374                const ast::FunctionDecl * funcDecl = nullptr;
     375        };
     376
     377        void ReturnFixer_New::previsit( const ast::FunctionDecl * decl ) {
     378                GuardValue( funcDecl ) = decl;
     379        }
     380
     381        const ast::ReturnStmt * ReturnFixer_New::previsit(
     382                        const ast::ReturnStmt * stmt ) {
     383                auto & returns = funcDecl->returns;
     384                assert( returns.size() < 2 );
     385                // Hands off if the function returns a reference.
     386                // Don't allocate a temporary if the address is returned.
     387                if ( stmt->expr && 1 == returns.size() ) {
     388                        ast::ptr<ast::DeclWithType> retDecl = returns.front();
     389                        if ( isConstructable( retDecl->get_type() ) ) {
     390                                // Explicitly construct the return value using the return
     391                                // expression and the retVal object.
     392                                assertf( "" != retDecl->name,
     393                                        "Function %s has unnamed return value.\n",
     394                                        funcDecl->name.c_str() );
     395
     396                                auto retVal = retDecl.strict_as<ast::ObjectDecl>();
     397                                if ( auto varExpr = stmt->expr.as<ast::VariableExpr>() ) {
     398                                        // Check if the return statement is already set up.
     399                                        if ( varExpr->var == retVal ) return stmt;
     400                                }
     401                                ast::ptr<ast::Stmt> ctorStmt = genCtorDtor(
     402                                        retVal->location, "?{}", retVal, stmt->expr );
     403                                assertf( ctorStmt,
     404                                        "ReturnFixer: genCtorDtor returned nllptr: %s / %s",
     405                                        toString( retVal ).c_str(),
     406                                        toString( stmt->expr ).c_str() );
     407                                        stmtsToAddBefore.push_back( ctorStmt );
     408
     409                                // Return the retVal object.
     410                                ast::ReturnStmt * mutStmt = ast::mutate( stmt );
     411                                mutStmt->expr = new ast::VariableExpr(
     412                                        stmt->location, retDecl );
     413                                return mutStmt;
     414                        }
     415                }
     416                return stmt;
     417        }
     418
     419} // namespace
     420
     421        void genInit( ast::TranslationUnit & transUnit ) {
     422                ast::Pass<HoistArrayDimension_NoResolve_New>::run( transUnit );
     423                ast::Pass<ReturnFixer_New>::run( transUnit );
     424        }
     425
    296426        void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
    297427                PassVisitor<CtorDtor> ctordtor;
  • src/InitTweak/GenInit.h

    r94647b0b r7770cc8  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:31:19 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct 22 16:08:00 2021
     13// Update Count     : 6
    1414//
    1515
     
    2727        /// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
    2828        void genInit( std::list< Declaration * > & translationUnit );
     29        void genInit( ast::TranslationUnit & translationUnit );
    2930
    3031        /// Converts return statements into copy constructor calls on the hidden return variable
  • src/InitTweak/InitTweak.cc

    r94647b0b r7770cc8  
    99// Author           : Rob Schluntz
    1010// Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 16 20:57:22 2021
    13 // Update Count     : 18
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Nov 19 19:22:00 2021
     13// Update Count     : 19
    1414//
    1515
     
    540540        }
    541541
     542        const ast::Type * getTypeofThis( const ast::FunctionType * ftype ) {
     543                assertf( ftype, "getTypeofThis: nullptr ftype" );
     544                const std::vector<ast::ptr<ast::Type>> & params = ftype->params;
     545                assertf( !params.empty(), "getTypeofThis: ftype with 0 parameters: %s",
     546                                toString( ftype ).c_str() );
     547                const ast::ReferenceType * refType =
     548                        params.front().strict_as<ast::ReferenceType>();
     549                return refType->base;
     550        }
     551
    542552        ObjectDecl * getParamThis( FunctionType * ftype ) {
    543553                assertf( ftype, "getParamThis: nullptr ftype" );
  • src/InitTweak/InitTweak.h

    r94647b0b r7770cc8  
    1010// Created On       : Fri May 13 11:26:36 2016
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 19 14:18:00 2019
    13 // Update Count     : 6
     12// Last Modified On : Fri Nov 19 14:18:00 2021
     13// Update Count     : 7
    1414//
    1515
     
    3535        /// returns the base type of the first parameter to a constructor/destructor/assignment function
    3636        Type * getTypeofThis( FunctionType * ftype );
     37        const ast::Type * getTypeofThis( const ast::FunctionType * ftype );
    3738
    3839        /// returns the first parameter of a constructor/destructor/assignment function
  • src/Parser/parser.yy

    r94647b0b r7770cc8  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Sep 11 08:20:44 2021
    13 // Update Count     : 5040
     12// Last Modified On : Fri Oct 15 09:20:17 2021
     13// Update Count     : 5163
    1414//
    1515
     
    3131// from ANSI90 to ANSI11 C are marked with the comment "C99/C11".
    3232
    33 // This grammar also has two levels of extensions. The first extensions cover most of the GCC C extensions All of the
     33// This grammar also has two levels of extensions. The first extensions cover most of the GCC C extensions. All of the
    3434// syntactic extensions for GCC C are marked with the comment "GCC". The second extensions are for Cforall (CFA), which
    3535// fixes several of C's outstanding problems and extends C with many modern language concepts. All of the syntactic
     
    6969        // 2. String encodings are transformed into canonical form (one encoding at start) so the encoding can be found
    7070        //    without searching the string, e.g.: "abc" L"def" L"ghi" => L"abc" "def" "ghi". Multiple encodings must match,
    71         //    i.e., u"a" U"b" L"c" is disallowed.
     71        //    e.g., u"a" U"b" L"c" is disallowed.
    7272
    7373        if ( from[0] != '"' ) {                                                         // encoding ?
     
    310310%token ATassign                                                                                 // @=
    311311
    312 %type<tok> identifier
    313 %type<tok> identifier_or_type_name  attr_name
     312%type<tok> identifier                                   identifier_at                           identifier_or_type_name         attr_name
    314313%type<tok> quasi_keyword
    315314%type<constant> string_literal
     
    327326%type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
    328327%type<en> comma_expression                              comma_expression_opt
    329 %type<en> argument_expression_list_opt  argument_expression                     default_initializer_opt
     328%type<en> argument_expression_list_opt  argument_expression_list        argument_expression                     default_initializer_opt
    330329%type<ifctl> if_control_expression
    331330%type<fctl> for_control_expression              for_control_expression_list
     
    559558        IDENTIFIER
    560559        | quasi_keyword
     560        ;
     561
     562identifier_at:
     563        identifier
    561564        | '@'                                                                                           // CFA
    562565                { Token tok = { new string( DeclarationNode::anonymous.newName() ), yylval.tok.loc }; $$ = tok; }
     
    693696        // empty
    694697                { $$ = nullptr; }
    695         | argument_expression
     698        | argument_expression_list
     699        ;
     700
     701argument_expression_list:
     702        argument_expression
    696703        | argument_expression_list_opt ',' argument_expression
    697704                { $$ = (ExpressionNode *)($1->set_last( $3 )); }
     
    731738        | FLOATINGconstant fraction_constants_opt
    732739                { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
    733         | identifier fraction_constants_opt
     740        | identifier_at fraction_constants_opt                          // CFA, allow anonymous fields
    734741                {
    735742                        $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     
    10841091        comma_expression_opt ';'
    10851092                { $$ = new StatementNode( build_expr( $1 ) ); }
     1093        | MUTEX '(' ')' comma_expression ';'
     1094                { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); }
     1095                // { SemanticError( yylloc, "Mutex expression is currently unimplemented." ); $$ = nullptr; }
    10861096        ;
    10871097
     
    11821192
    11831193iteration_statement:
    1184         WHILE '(' push if_control_expression ')' statement pop
    1185                 { $$ = new StatementNode( build_while( $4, maybe_build_compound( $6 ) ) ); }
    1186         | WHILE '(' ')' statement                                                       // CFA => while ( 1 )
     1194        WHILE '(' ')' statement                                                         // CFA => while ( 1 )
    11871195                { $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
    1188         | DO statement WHILE '(' comma_expression ')' ';'
    1189                 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
     1196        | WHILE '(' if_control_expression ')' statement         %prec THEN
     1197                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
     1198        | WHILE '(' if_control_expression ')' statement ELSE statement // CFA
     1199                { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    11901200        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    11911201                { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
    1192         | FOR '(' push for_control_expression_list ')' statement pop
    1193                 { $$ = new StatementNode( build_for( $4, maybe_build_compound( $6 ) ) ); }
     1202        | DO statement WHILE '(' comma_expression ')' ';'       %prec THEN
     1203                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
     1204        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
     1205                { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    11941206        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
    11951207                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
     1208        | FOR '(' for_control_expression_list ')' statement     %prec THEN
     1209                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
     1210        | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
     1211                { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    11961212        ;
    11971213
     
    13391355with_statement:
    13401356        WITH '(' tuple_expression_list ')' statement
    1341                 {
    1342                         $$ = new StatementNode( build_with( $3, $5 ) );
    1343                 }
     1357                { $$ = new StatementNode( build_with( $3, $5 ) ); }
    13441358        ;
    13451359
    13461360// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".
    13471361mutex_statement:
    1348         MUTEX '(' argument_expression_list_opt ')' statement
     1362        MUTEX '(' argument_expression_list ')' statement
    13491363                { $$ = new StatementNode( build_mutex( $3, $5 ) ); }
    13501364        ;
     
    24752489designation:
    24762490        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    2477         | identifier ':'                                                                        // GCC, field name
     2491        | identifier_at ':'                                                                     // GCC, field name
    24782492                { $$ = new ExpressionNode( build_varref( $1 ) ); }
    24792493        ;
     
    24872501
    24882502designator:
    2489         '.' identifier                                                                          // C99, field name
     2503        '.' identifier_at                                                                       // C99, field name
    24902504                { $$ = new ExpressionNode( build_varref( $2 ) ); }
    24912505        | '[' push assignment_expression pop ']'                        // C99, single array element
     
    29192933
    29202934paren_identifier:
    2921         identifier
     2935        identifier_at
    29222936                { $$ = DeclarationNode::newName( $1 ); }
    29232937        | '(' paren_identifier ')'                                                      // redundant parenthesis
  • src/ResolvExpr/module.mk

    r94647b0b r7770cc8  
    6161      ResolvExpr/WidenMode.h
    6262
     63SRC += $(SRC_RESOLVEXPR) \
     64        ResolvExpr/AlternativePrinter.cc \
     65        ResolvExpr/AlternativePrinter.h \
     66        ResolvExpr/CandidatePrinter.cpp \
     67        ResolvExpr/CandidatePrinter.hpp
    6368
    64 SRC += $(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc ResolvExpr/AlternativePrinter.h
    6569SRCDEMANGLE += $(SRC_RESOLVEXPR)
  • src/SymTab/Validate.cc

    r94647b0b r7770cc8  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:43:34 2019
    13 // Update Count     : 363
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Nov 12 11:00:00 2021
     13// Update Count     : 364
    1414//
    1515
     
    334334        };
    335335
    336         void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
     336        void validate_A( std::list< Declaration * > & translationUnit ) {
    337337                PassVisitor<EnumAndPointerDecay_old> epc;
    338                 PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
    339                 PassVisitor<ResolveEnumInitializers> rei( nullptr );
    340                 PassVisitor<ForallPointerDecay_old> fpd;
    341                 PassVisitor<CompoundLiteral> compoundliteral;
    342                 PassVisitor<ValidateGenericParameters> genericParams;
    343                 PassVisitor<LabelAddressFixer> labelAddrFixer;
    344338                PassVisitor<HoistTypeDecls> hoistDecls;
    345                 PassVisitor<FixQualifiedTypes> fixQual;
    346 
    347339                {
    348340                        Stats::Heap::newPass("validate-A");
     
    354346                        acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling
    355347                }
     348        }
     349
     350        void validate_B( std::list< Declaration * > & translationUnit ) {
     351                PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
     352                PassVisitor<FixQualifiedTypes> fixQual;
    356353                {
    357354                        Stats::Heap::newPass("validate-B");
     
    362359                        EliminateTypedef::eliminateTypedef( translationUnit );
    363360                }
     361        }
     362
     363        void validate_C( std::list< Declaration * > & translationUnit ) {
     364                PassVisitor<ValidateGenericParameters> genericParams;
     365                PassVisitor<ResolveEnumInitializers> rei( nullptr );
    364366                {
    365367                        Stats::Heap::newPass("validate-C");
     
    381383                        });
    382384                }
     385        }
     386
     387        void validate_D( std::list< Declaration * > & translationUnit ) {
     388                PassVisitor<ForallPointerDecay_old> fpd;
    383389                {
    384390                        Stats::Heap::newPass("validate-D");
     
    397403                        });
    398404                }
     405        }
     406
     407        void validate_E( std::list< Declaration * > & translationUnit ) {
     408                PassVisitor<CompoundLiteral> compoundliteral;
    399409                {
    400410                        Stats::Heap::newPass("validate-E");
     
    415425                        }
    416426                }
     427        }
     428
     429        void validate_F( std::list< Declaration * > & translationUnit ) {
     430                PassVisitor<LabelAddressFixer> labelAddrFixer;
    417431                {
    418432                        Stats::Heap::newPass("validate-F");
     
    437451                        }
    438452                }
     453        }
     454
     455        void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
     456                validate_A( translationUnit );
     457                validate_B( translationUnit );
     458                validate_C( translationUnit );
     459                validate_D( translationUnit );
     460                validate_E( translationUnit );
     461                validate_F( translationUnit );
    439462        }
    440463
  • src/SymTab/Validate.h

    r94647b0b r7770cc8  
    3535        void validateType( Type *type, const Indexer *indexer );
    3636
     37        // Sub-passes of validate.
     38        void validate_A( std::list< Declaration * > &translationUnit );
     39        void validate_B( std::list< Declaration * > &translationUnit );
     40        void validate_C( std::list< Declaration * > &translationUnit );
     41        void validate_D( std::list< Declaration * > &translationUnit );
     42        void validate_E( std::list< Declaration * > &translationUnit );
     43        void validate_F( std::list< Declaration * > &translationUnit );
     44
    3745        const ast::Type * validateType(
    3846                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab );
  • src/Tuples/TupleExpansionNew.cpp

    r94647b0b r7770cc8  
    2121                void previsit( const ast::UntypedMemberExpr * ) { visit_children = false; }
    2222        const ast::Expr * postvisit( const ast::UntypedMemberExpr * memberExpr );
     23        };
     24        struct UniqueExprExpander final : public ast::WithDeclsToAdd<> {
     25                const ast::Expr * postvisit( const ast::UniqueExpr * unqExpr );
     26                std::map< int, ast::ptr<ast::Expr> > decls; // not vector, because order added may not be increasing order
    2327        };
    2428} // namespace
     
    6670        }
    6771} // namespace
     72
     73void expandUniqueExpr( ast::TranslationUnit & translationUnit ) {
     74        ast::Pass< UniqueExprExpander >::run( translationUnit );
     75}
     76
     77namespace {
     78        const ast::Expr * UniqueExprExpander::postvisit( const ast::UniqueExpr * unqExpr ) {
     79                const CodeLocation loc = unqExpr->location;
     80                const int id = unqExpr->id;
     81
     82                // on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
     83                // and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
     84                if ( ! decls.count( id ) ) {
     85                        ast::ptr< ast::Expr > assignUnq;
     86                        const ast::VariableExpr * var = unqExpr->var;
     87                        if ( unqExpr->object ) {
     88                                // an object was generated to represent this unique expression -- it should be added to the list of declarations now
     89                                declsToAddBefore.push_back( unqExpr->object.as< ast::Decl >() );
     90                                // deep copy required due to unresolved issues with UniqueExpr
     91                                assignUnq = ast::UntypedExpr::createAssign( loc, var, unqExpr->expr );
     92                        } else {
     93                                const auto commaExpr = unqExpr->expr.strict_as< ast::CommaExpr >();
     94                                assignUnq = commaExpr->arg1;
     95                        }
     96                        auto finished = new ast::ObjectDecl( loc, toString( "_unq", id, "_finished_" ), new ast::BasicType( ast::BasicType::Kind::Bool ),
     97                                new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) ), {}, ast::Linkage::Cforall );
     98                        declsToAddBefore.push_back( finished );
     99                        // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
     100                        // This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
     101                        auto assignFinished = ast::UntypedExpr::createAssign( loc, new ast::VariableExpr( loc, finished ),
     102                                ast::ConstantExpr::from_int( loc, 1 ) );
     103                        auto condExpr = new ast::ConditionalExpr( loc, new ast::VariableExpr( loc, finished ), var,
     104                                new ast::CommaExpr( loc, new ast::CommaExpr( loc, assignUnq, assignFinished ), var ) );
     105                        condExpr->result = var->result;
     106                        condExpr->env = unqExpr->env;
     107                        decls[id] = condExpr;
     108                }
     109                //delete unqExpr;
     110                return ast::deepCopy(decls[id].get());
     111        }
     112} // namespace
    68113} // namespace Tuples
  • src/Tuples/Tuples.h

    r94647b0b r7770cc8  
    4646        /// replaces UniqueExprs with a temporary variable and one call
    4747        void expandUniqueExpr( std::list< Declaration * > & translationUnit );
     48        void expandUniqueExpr( ast::TranslationUnit & translationUnit );
    4849
    4950        /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
  • src/Validate/FindSpecialDecls.h

    r94647b0b r7770cc8  
    99// Author           : Rob Schluntz
    1010// Created On       : Thu Aug 30 09:49:02 2018
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Thu Aug 30 09:51:12 2018
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Nov 10 15:16:00 2021
     13// Update Count     : 3
    1414//
    1515
     
    2222class StructDecl;
    2323class Type;
     24
     25namespace ast {
     26        class TranslationUnit;
     27}
    2428
    2529namespace Validate {
     
    3842        /// find and remember some of the special declarations that are useful for generating code, so that they do not have to be discovered multiple times.
    3943        void findSpecialDecls( std::list< Declaration * > & translationUnit );
     44
     45/// find and remember some of the special declarations that are useful for
     46/// generating code, so that they do not have to be discovered multiple times.
     47void findGlobalDecls( ast::TranslationUnit & translationUnit );
     48
    4049} // namespace Validate
    4150
  • src/Validate/module.mk

    r94647b0b r7770cc8  
    1515###############################################################################
    1616
    17 SRC += Validate/HandleAttributes.cc Validate/HandleAttributes.h Validate/FindSpecialDecls.cc Validate/FindSpecialDecls.h
    18 SRCDEMANGLE += Validate/HandleAttributes.cc Validate/HandleAttributes.h Validate/FindSpecialDecls.cc Validate/FindSpecialDecls.h
     17SRC_VALIDATE = \
     18        Validate/HandleAttributes.cc \
     19        Validate/HandleAttributes.h \
     20        Validate/InitializerLength.cpp \
     21        Validate/InitializerLength.hpp \
     22        Validate/LabelAddressFixer.cpp \
     23        Validate/LabelAddressFixer.hpp \
     24        Validate/FindSpecialDeclsNew.cpp \
     25        Validate/FindSpecialDecls.cc \
     26        Validate/FindSpecialDecls.h
     27
     28SRC += $(SRC_VALIDATE)
     29SRCDEMANGLE += $(SRC_VALIDATE)
  • src/main.cc

    r94647b0b r7770cc8  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Henry Xue
    12 // Last Modified On : Mon Aug 23 15:42:08 2021
    13 // Update Count     : 650
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Nov 12 11:06:00 2021
     13// Update Count     : 658
    1414//
    1515
     
    4343#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    4444#include "Common/CompilerError.h"           // for CompilerError
     45#include "Common/DeclStats.hpp"             // for printDeclStats
     46#include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
    4547#include "Common/Stats.h"
    4648#include "Common/PassVisitor.h"
     
    5153#include "ControlStruct/ExceptDecl.h"       // for translateExcept
    5254#include "ControlStruct/ExceptTranslate.h"  // for translateEHM
     55#include "ControlStruct/FixLabels.hpp"      // for fixLabels
    5356#include "ControlStruct/Mutate.h"           // for mutate
    5457#include "GenPoly/Box.h"                    // for box
     
    6265#include "Parser/TypedefTable.h"            // for TypedefTable
    6366#include "ResolvExpr/AlternativePrinter.h"  // for AlternativePrinter
     67#include "ResolvExpr/CandidatePrinter.hpp"  // for printCandidates
    6468#include "ResolvExpr/Resolver.h"            // for resolve
    6569#include "SymTab/Validate.h"                // for validate
     
    6872#include "SynTree/Visitor.h"                // for acceptAll
    6973#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
     74#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
     75#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
     76#include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
    7077#include "Virtual/ExpandCasts.h"            // for expandCasts
    7178
     
    314321
    315322                // add the assignment statement after the initialization of a type parameter
    316                 PASS( "Validate", SymTab::validate( translationUnit, symtabp ) );
    317                 if ( symtabp ) {
    318                         deleteAll( translationUnit );
    319                         return EXIT_SUCCESS;
    320                 } // if
    321 
    322                 if ( expraltp ) {
    323                         PassVisitor<ResolvExpr::AlternativePrinter> printer( cout );
    324                         acceptAll( translationUnit, printer );
    325                         return EXIT_SUCCESS;
    326                 } // if
    327 
    328                 if ( validp ) {
    329                         dump( translationUnit );
    330                         return EXIT_SUCCESS;
    331                 } // if
    332 
    333                 PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) );
    334                 PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    335                 PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
    336                 PASS( "Gen Init", InitTweak::genInit( translationUnit ) );
    337 
    338                 if ( libcfap ) {
    339                         // generate the bodies of cfa library functions
    340                         LibCfa::makeLibCfa( translationUnit );
    341                 } // if
    342 
    343                 if ( declstatsp ) {
    344                         CodeTools::printDeclStats( translationUnit );
    345                         deleteAll( translationUnit );
    346                         return EXIT_SUCCESS;
    347                 } // if
    348 
    349                 if ( bresolvep ) {
    350                         dump( translationUnit );
    351                         return EXIT_SUCCESS;
    352                 } // if
     323                PASS( "Validate-A", SymTab::validate_A( translationUnit ) );
     324                PASS( "Validate-B", SymTab::validate_B( translationUnit ) );
     325                PASS( "Validate-C", SymTab::validate_C( translationUnit ) );
     326                PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
     327                PASS( "Validate-E", SymTab::validate_E( translationUnit ) );
    353328
    354329                CodeTools::fillLocations( translationUnit );
    355 
    356                 if ( resolvprotop ) {
    357                         CodeTools::dumpAsResolvProto( translationUnit );
    358                         return EXIT_SUCCESS;
    359                 } // if
    360330
    361331                if( useNewAST ) {
     
    366336                        auto transUnit = convert( move( translationUnit ) );
    367337
     338                        forceFillCodeLocations( transUnit );
     339
     340                        PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
     341                        PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
     342                        PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) );
     343
     344                        if ( symtabp ) {
     345                                return EXIT_SUCCESS;
     346                        } // if
     347
     348                        if ( expraltp ) {
     349                                ResolvExpr::printCandidates( transUnit );
     350                                return EXIT_SUCCESS;
     351                        } // if
     352
     353                        if ( validp ) {
     354                                dump( move( transUnit ) );
     355                                return EXIT_SUCCESS;
     356                        } // if
     357
     358                        PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) );
     359                        PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) );
     360                        PASS( "Fix Names", CodeGen::fixNames( transUnit ) );
     361                        PASS( "Gen Init", InitTweak::genInit( transUnit ) );
    368362                        PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
    369                        
     363
     364                        if ( libcfap ) {
     365                                // Generate the bodies of cfa library functions.
     366                                LibCfa::makeLibCfa( transUnit );
     367                        } // if
     368
     369                        if ( declstatsp ) {
     370                                printDeclStats( transUnit );
     371                                return EXIT_SUCCESS;
     372                        } // if
     373
     374                        if ( bresolvep ) {
     375                                dump( move( transUnit ) );
     376                                return EXIT_SUCCESS;
     377                        } // if
     378
     379                        if ( resolvprotop ) {
     380                                dumpAsResolverProto( transUnit );
     381                                return EXIT_SUCCESS;
     382                        } // if
     383
    370384                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    371385                        if ( exprp ) {
     
    377391
    378392                        PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
     393
     394                        // fix ObjectDecl - replaces ConstructorInit nodes
     395                        if ( ctorinitp ) {
     396                                dump( move( transUnit ) );
     397                                return EXIT_SUCCESS;
     398                        } // if
     399
     400                        // Currently not working due to unresolved issues with UniqueExpr
     401                        PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    379402                        translationUnit = convert( move( transUnit ) );
    380403                } else {
     404                        PASS( "Validate-F", SymTab::validate_F( translationUnit ) );
     405
     406                        if ( symtabp ) {
     407                                deleteAll( translationUnit );
     408                                return EXIT_SUCCESS;
     409                        } // if
     410
     411                        if ( expraltp ) {
     412                                PassVisitor<ResolvExpr::AlternativePrinter> printer( cout );
     413                                acceptAll( translationUnit, printer );
     414                                return EXIT_SUCCESS;
     415                        } // if
     416
     417                        if ( validp ) {
     418                                dump( translationUnit );
     419                                return EXIT_SUCCESS;
     420                        } // if
     421
     422                        PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) );
     423                        PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
     424                        PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
     425                        PASS( "Gen Init", InitTweak::genInit( translationUnit ) );
    381426                        PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( translationUnit ) );
     427
     428                        if ( libcfap ) {
     429                                // Generate the bodies of cfa library functions.
     430                                LibCfa::makeLibCfa( translationUnit );
     431                        } // if
     432
     433                        if ( declstatsp ) {
     434                                CodeTools::printDeclStats( translationUnit );
     435                                deleteAll( translationUnit );
     436                                return EXIT_SUCCESS;
     437                        } // if
     438
     439                        if ( bresolvep ) {
     440                                dump( translationUnit );
     441                                return EXIT_SUCCESS;
     442                        } // if
     443
     444                        CodeTools::fillLocations( translationUnit );
     445
     446                        if ( resolvprotop ) {
     447                                CodeTools::dumpAsResolvProto( translationUnit );
     448                                return EXIT_SUCCESS;
     449                        } // if
    382450
    383451                        PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     
    388456
    389457                        PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
     458
     459                        // fix ObjectDecl - replaces ConstructorInit nodes
     460                        if ( ctorinitp ) {
     461                                dump ( translationUnit );
     462                                return EXIT_SUCCESS;
     463                        } // if
     464
     465                        PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    390466                }
    391 
    392                 // fix ObjectDecl - replaces ConstructorInit nodes
    393                 if ( ctorinitp ) {
    394                         dump ( translationUnit );
    395                         return EXIT_SUCCESS;
    396                 } // if
    397 
    398                 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    399467
    400468                PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
     
    443511                PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );
    444512
    445                 CodeGen::FixMain::fix( *output, (PreludeDirector + "/bootloader.c").c_str() );
     513                CodeGen::FixMain::fix( translationUnit, *output,
     514                                (PreludeDirector + "/bootloader.c").c_str() );
    446515                if ( output != &cout ) {
    447516                        delete output;
Note: See TracChangeset for help on using the changeset viewer.