Changeset c28ea4e for src


Ignore:
Timestamp:
Nov 4, 2020, 2:56:30 PM (5 years ago)
Author:
Colby Alexander Parsons <caparsons@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
eeb5023
Parents:
4b30e8cc (diff), a3f5208a (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:
2 added
43 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r4b30e8cc rc28ea4e  
    2525#include "AST/Init.hpp"
    2626#include "AST/Stmt.hpp"
     27#include "AST/TranslationUnit.hpp"
    2728#include "AST/TypeSubstitution.hpp"
    2829
     
    4748
    4849//================================================================================================
    49 namespace {
     50namespace ast {
    5051
    5152// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
    5253// allow us to use the same stratagy in the new ast.
     54// xxx - since convert back pass works, this concern seems to be unnecessary.
     55
     56// these need to be accessed in new FixInit now
    5357ast::Type * sizeType = nullptr;
    5458ast::FunctionDecl * dereferenceOperator = nullptr;
     
    6367        using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
    6468        Cache cache;
     69
     70        // Statements can no longer be shared.
     71        // however, since StmtExprResult is now implemented, need to still maintain
     72        // readonly references.
     73        Cache readonlyCache;
    6574
    6675        template<typename T>
     
    154163        }
    155164
    156         const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
    157                 auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth );
    158                 auto&& type = get<Type>().accept1( node->type );
    159                 auto&& init = get<Initializer>().accept1( node->init );
    160                 auto&& attr = get<Attribute>().acceptL( node->attributes );
     165        const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {       
    161166                if ( inCache( node ) ) {
    162167                        return nullptr;
    163168                }
     169                auto bfwd = get<Expression>().accept1( node->bitfieldWidth );
     170                auto type = get<Type>().accept1( node->type );
     171                auto attr = get<Attribute>().acceptL( node->attributes );
     172
    164173                auto decl = new ObjectDecl(
    165174                        node->name,
     
    168177                        bfwd,
    169178                        type->clone(),
    170                         init,
     179                        nullptr, // prevent infinite loop
    171180                        attr,
    172181                        Type::FuncSpecifiers( node->funcSpec.val )
    173182                );
    174                 return declWithTypePostamble( decl, node );
     183
     184                // handles the case where node->init references itself
     185                // xxx - does it really happen?
     186                declWithTypePostamble(decl, node);
     187                auto init = get<Initializer>().accept1( node->init );
     188                decl->init = init;
     189               
     190                this->node = decl;
     191                return nullptr;
    175192        }
    176193
     
    205222                decl->statements = get<CompoundStmt>().accept1( node->stmts );
    206223                decl->withExprs = get<Expression>().acceptL( node->withExprs );
    207                 if ( dereferenceOperator == node ) {
     224                if ( ast::dereferenceOperator == node ) {
    208225                        Validate::dereferenceOperator = decl;
    209226                }
    210                 if ( dtorStructDestroy == node ) {
     227                if ( ast::dtorStructDestroy == node ) {
    211228                        Validate::dtorStructDestroy = decl;
    212229                }
     
    267284                );
    268285
    269                 if ( dtorStruct == node ) {
     286                if ( ast::dtorStruct == node ) {
    270287                        Validate::dtorStruct = decl;
    271288                }
     
    320337
    321338        const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
    322                 cache.emplace( node, stmt );
     339                // force statements in old tree to be unique.
     340                // cache.emplace( node, stmt );
     341                readonlyCache.emplace( node, stmt );
    323342                stmt->location = node->location;
    324343                stmt->labels = makeLabelL( stmt, node->labels );
     
    337356                if ( inCache( node ) ) return nullptr;
    338357                auto stmt = new ExprStmt( nullptr );
    339                 cache.emplace( node, stmt );
    340358                stmt->expr = get<Expression>().accept1( node->expr );
    341359                return stmtPostamble( stmt, node );
     
    10111029                auto stmts = node->stmts;
    10121030                // disable sharing between multiple StmtExprs explicitly.
    1013                 if (inCache(stmts)) {
    1014                         stmts = ast::deepCopy(stmts.get());
    1015                 }
     1031                // this should no longer be true.
     1032
    10161033                auto rslt = new StmtExpr(
    10171034                        get<CompoundStmt>().accept1(stmts)
     
    10201037                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
    10211038                rslt->dtors       = get<Expression>().acceptL(node->dtors);
     1039                if (node->resultExpr) {
     1040                        // this MUST be found by children visit
     1041                        rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr));
     1042                }
    10221043
    10231044                auto expr = visitBaseExpr( node, rslt );
     
    10361057
    10371058                auto expr = visitBaseExpr( node, rslt );
    1038                 this->node = expr;
     1059                this->node = expr->clone();
    10391060                return nullptr;
    10401061        }
     
    11261147                auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
    11271148                // I believe this should always be a BasicType.
    1128                 if ( sizeType == node ) {
     1149                if ( ast::sizeType == node ) {
    11291150                        Validate::SizeType = type;
    11301151                }
     
    13841405};
    13851406
    1386 std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit ) {
     1407std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit ) {
    13871408        ConverterNewToOld c;
    13881409        std::list< Declaration * > decls;
    1389         for(auto d : translationUnit) {
     1410        for(auto d : translationUnit.decls) {
    13901411                decls.emplace_back( c.decl( d ) );
    13911412        }
     
    15291550
    15301551                // function type is now derived from parameter decls instead of storing them
     1552
     1553                /*
    15311554                auto ftype = new ast::FunctionType((ast::ArgumentFlag)old->type->isVarArgs, cv(old->type));
    15321555                ftype->params.reserve(paramVars.size());
     
    15401563                }
    15411564                ftype->forall = std::move(forall);
    1542                 visitType(old->type, ftype);
     1565                */
     1566
     1567                // can function type have attributes? seems not to be the case.
     1568                // visitType(old->type, ftype);
    15431569
    15441570                auto decl = new ast::FunctionDecl{
     
    15461572                        old->name,
    15471573                        // GET_ACCEPT_1(type, FunctionType),
     1574                        std::move(forall),
    15481575                        std::move(paramVars),
    15491576                        std::move(returnVars),
     
    15521579                        { old->linkage.val },
    15531580                        GET_ACCEPT_V(attributes, Attribute),
    1554                         { old->get_funcSpec().val }
     1581                        { old->get_funcSpec().val },
     1582                        old->type->isVarArgs
    15551583                };
    15561584
    1557                 decl->type = ftype;
     1585                // decl->type = ftype;
    15581586                cache.emplace( old, decl );
    15591587
     
    15701598
    15711599                if ( Validate::dereferenceOperator == old ) {
    1572                         dereferenceOperator = decl;
     1600                        ast::dereferenceOperator = decl;
    15731601                }
    15741602
    15751603                if ( Validate::dtorStructDestroy == old ) {
    1576                         dtorStructDestroy = decl;
     1604                        ast::dtorStructDestroy = decl;
    15771605                }
    15781606        }
     
    15991627
    16001628                if ( Validate::dtorStruct == old ) {
    1601                         dtorStruct = decl;
     1629                        ast::dtorStruct = decl;
    16021630                }
    16031631        }
     
    25312559                // I believe this should always be a BasicType.
    25322560                if ( Validate::SizeType == old ) {
    2533                         sizeType = type;
     2561                        ast::sizeType = type;
    25342562                }
    25352563                visitType( old, type );
     
    27762804#undef GET_ACCEPT_1
    27772805
    2778 std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit ) {
     2806ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit ) {
    27792807        ConverterOldToNew c;
    2780         std::list< ast::ptr< ast::Decl > > decls;
     2808        ast::TranslationUnit unit;
    27812809        for(auto d : translationUnit) {
    27822810                d->accept( c );
    2783                 decls.emplace_back( c.decl() );
     2811                unit.decls.emplace_back( c.decl() );
    27842812        }
    27852813        deleteAll(translationUnit);
    2786         return decls;
     2814        return unit;
    27872815}
  • src/AST/Convert.hpp

    r4b30e8cc rc28ea4e  
    1818#include <list>
    1919
    20 #include "AST/Node.hpp"
    21 
    2220class Declaration;
    2321namespace ast {
    24         class Decl;
     22        class TranslationUnit;
    2523};
    2624
    27 std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit );
    28 std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit );
     25std::list< Declaration * > convert( const ast::TranslationUnit && translationUnit );
     26ast::TranslationUnit convert( const std::list< Declaration * > && translationUnit );
  • src/AST/Decl.cpp

    r4b30e8cc rc28ea4e  
    4848
    4949// --- FunctionDecl
     50
     51FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
     52                std::vector<ptr<TypeDecl>>&& forall,
     53                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
     54                CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
     55                std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
     56        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     57          stmts( stmts ) {
     58                  FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
     59                  for (auto & param : this->params) {
     60                          ftype->params.emplace_back(param->get_type());
     61                  }
     62                  for (auto & ret : this->returns) {
     63                          ftype->returns.emplace_back(ret->get_type());
     64                  }
     65                  ftype->forall = std::move(forall);
     66                  this->type = ftype;
     67          }
     68
    5069
    5170const Type * FunctionDecl::get_type() const { return type.get(); }
  • src/AST/Decl.hpp

    r4b30e8cc rc28ea4e  
    131131        std::vector< ptr<Expr> > withExprs;
    132132
    133         FunctionDecl( const CodeLocation & loc, const std::string & name,
     133        FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
    134134                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    135135                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
    136                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {})
    137         : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
    138           stmts( stmts ) {}
     136                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
     137        // : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
     138        //  stmts( stmts ) {}
    139139
    140140        const Type * get_type() const override;
  • src/AST/DeclReplacer.cpp

    r4b30e8cc rc28ea4e  
    3838                        const ast::TypeInstType * previsit( const ast::TypeInstType * );
    3939                };
     40
     41                struct VarExprReplacer {
     42                private:
     43                        const ExprMap & exprMap;
     44                       
     45                public:
     46                        VarExprReplacer(const ExprMap & exprMap): exprMap (exprMap) {}
     47
     48                        const Expr * postvisit (const VariableExpr *);
     49                };
    4050        }
    4151
     
    5464                DeclMap declMap;
    5565                return replace( node, declMap, typeMap, debug );
     66        }
     67
     68        const ast::Node * replace( const ast::Node * node, const ExprMap & exprMap) {
     69                Pass<VarExprReplacer> replacer = {exprMap};
     70                return node->accept( replacer );
    5671        }
    5772
     
    88103                        return ninst;
    89104                }
     105
     106                const Expr * VarExprReplacer::postvisit( const VariableExpr * expr ) {
     107                        if (!exprMap.count(expr->var)) return expr;
     108
     109                        return exprMap.at(expr->var);
     110                }
     111
    90112        }
    91113}
  • src/AST/DeclReplacer.hpp

    r4b30e8cc rc28ea4e  
    2323        class DeclWithType;
    2424        class TypeDecl;
     25        class Expr;
    2526
    2627        namespace DeclReplacer {
    2728                using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
    2829                using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
     30                using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
    2931
    3032                const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
    3133                const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
    3234                const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
     35                const Node * replace( const Node * node, const ExprMap & exprMap);
    3336        }
    3437}
  • src/AST/Expr.cpp

    r4b30e8cc rc28ea4e  
    6767// --- UntypedExpr
    6868
    69 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) {
     69UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) {
    7070        assert( arg );
    7171
     
    9292}
    9393
    94 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) {
     94UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) {
    9595        assert( lhs && rhs );
    9696
     
    102102        }
    103103        return ret;
     104}
     105
     106// --- VariableExpr
     107
     108VariableExpr::VariableExpr( const CodeLocation & loc )
     109: Expr( loc ), var( nullptr ) {}
     110
     111VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
     112: Expr( loc ), var( v ) {
     113        assert( var );
     114        assert( var->get_type() );
     115        result = shallowCopy( var->get_type() );
     116}
     117
     118bool VariableExpr::get_lvalue() const {
     119        // It isn't always an lvalue, but it is never an rvalue.
     120        return true;
     121}
     122
     123VariableExpr * VariableExpr::functionPointer(
     124                const CodeLocation & loc, const FunctionDecl * decl ) {
     125        // wrap usually-determined result type in a pointer
     126        VariableExpr * funcExpr = new VariableExpr{ loc, decl };
     127        funcExpr->result = new PointerType{ funcExpr->result };
     128        return funcExpr;
    104129}
    105130
     
    238263}
    239264
    240 // --- VariableExpr
    241 
    242 VariableExpr::VariableExpr( const CodeLocation & loc )
    243 : Expr( loc ), var( nullptr ) {}
    244 
    245 VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
    246 : Expr( loc ), var( v ) {
    247         assert( var );
    248         assert( var->get_type() );
    249         result = shallowCopy( var->get_type() );
    250 }
    251 
    252 bool VariableExpr::get_lvalue() const {
    253         // It isn't always an lvalue, but it is never an rvalue.
    254         return true;
    255 }
    256 
    257 VariableExpr * VariableExpr::functionPointer(
    258                 const CodeLocation & loc, const FunctionDecl * decl ) {
    259         // wrap usually-determined result type in a pointer
    260         VariableExpr * funcExpr = new VariableExpr{ loc, decl };
    261         funcExpr->result = new PointerType{ funcExpr->result };
    262         return funcExpr;
    263 }
    264 
    265265// --- ConstantExpr
    266266
  • src/AST/Expr.hpp

    r4b30e8cc rc28ea4e  
    226226
    227227        /// Creates a new dereference expression
    228         static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
     228        static UntypedExpr * createDeref( const CodeLocation & loc, const Expr * arg );
    229229        /// Creates a new assignment expression
    230         static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
     230        static UntypedExpr * createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs );
    231231
    232232        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    247247private:
    248248        NameExpr * clone() const override { return new NameExpr{ *this }; }
     249        MUTATE_FRIEND
     250};
     251
     252/// A reference to a named variable.
     253class VariableExpr final : public Expr {
     254public:
     255        readonly<DeclWithType> var;
     256
     257        VariableExpr( const CodeLocation & loc );
     258        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
     259
     260        bool get_lvalue() const final;
     261
     262        /// generates a function pointer for a given function
     263        static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
     264
     265        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     266private:
     267        VariableExpr * clone() const override { return new VariableExpr{ *this }; }
    249268        MUTATE_FRIEND
    250269};
     
    392411};
    393412
    394 /// A reference to a named variable.
    395 class VariableExpr final : public Expr {
    396 public:
    397         readonly<DeclWithType> var;
    398 
    399         VariableExpr( const CodeLocation & loc );
    400         VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    401 
    402         bool get_lvalue() const final;
    403 
    404         /// generates a function pointer for a given function
    405         static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
    406 
    407         const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    408 private:
    409         VariableExpr * clone() const override { return new VariableExpr{ *this }; }
    410         MUTATE_FRIEND
    411 };
    412 
    413413/// A compile-time constant.
    414414/// Mostly carries C-source text from parse to code-gen, without interpretation.  E.g. strings keep their outer quotes and never have backslashes interpreted.
     
    422422                const CodeLocation & loc, const Type * ty, const std::string & r,
    423423                        std::optional<unsigned long long> i )
    424         : Expr( loc, ty ), rep( r ), ival( i ) {}
     424        : Expr( loc, ty ), rep( r ), ival( i ), underlyer(ty) {}
    425425
    426426        /// Gets the integer value of this constant, if one is appropriate to its type.
     
    617617
    618618        ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
    619         : Expr( loc, call->result ) { assert( call ); }
     619        : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
    620620
    621621        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    742742        std::vector<ptr<Expr>> dtors;              ///< destructor(s) for return variable(s)
    743743
     744        readonly<ExprStmt> resultExpr;
     745
    744746        StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
    745747
  • src/AST/Fwd.hpp

    r4b30e8cc rc28ea4e  
    137137typedef unsigned int UniqueId;
    138138
     139class TranslationUnit;
     140// TODO: Get from the TranslationUnit:
     141extern Type * sizeType;
     142extern FunctionDecl * dereferenceOperator;
     143extern StructDecl   * dtorStruct;
     144extern FunctionDecl * dtorStructDestroy;
     145
    139146}
  • src/AST/Node.hpp

    r4b30e8cc rc28ea4e  
    4949
    5050        bool unique() const { return strong_count == 1; }
     51        bool isManaged() const {return strong_count > 0; }
    5152
    5253private:
  • src/AST/Pass.hpp

    r4b30e8cc rc28ea4e  
    103103        /// Construct and run a pass on a translation unit.
    104104        template< typename... Args >
    105         static void run( std::list< ptr<Decl> > & decls, Args &&... args ) {
     105        static void run( TranslationUnit & decls, Args &&... args ) {
    106106                Pass<core_t> visitor( std::forward<Args>( args )... );
    107107                accept_all( decls, visitor );
     
    119119        // Versions of the above for older compilers.
    120120        template< typename... Args >
    121         static void run( std::list< ptr<Decl> > & decls ) {
     121        static void run( TranslationUnit & decls ) {
    122122                Pass<core_t> visitor;
    123123                accept_all( decls, visitor );
     
    228228        template<typename core_type>
    229229        friend void accept_all( std::list< ptr<Decl> > & decls, Pass<core_type>& visitor );
     230
     231        bool isInFunction() const {
     232                return inFunction;
     233        }
     234
    230235private:
    231236
     
    235240        const ast::Stmt * call_accept( const ast::Stmt * );
    236241        const ast::Expr * call_accept( const ast::Expr * );
     242
     243        // requests WithStmtsToAdd directly add to this statement, as if it is a compound.
     244
     245        const ast::Stmt * call_accept_as_compound(const ast::Stmt *);
    237246
    238247        template< typename node_t >
     
    257266        template<typename node_t, typename parent_t, typename child_t>
    258267        void maybe_accept(const node_t * &, child_t parent_t::* child);
     268
     269        template<typename node_t, typename parent_t, typename child_t>
     270        void maybe_accept_as_compound(const node_t * &, child_t parent_t::* child);
    259271
    260272private:
     
    284296private:
    285297        bool inFunction = false;
     298        bool atFunctionTop = false;
    286299};
    287300
     
    289302template<typename core_t>
    290303void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<core_t> & visitor );
     304
     305template<typename core_t>
     306void accept_all( ast::TranslationUnit &, ast::Pass<core_t> & visitor );
    291307
    292308//-------------------------------------------------------------------------------------------------
     
    371387struct WithVisitorRef {
    372388        Pass<core_t> * const visitor = nullptr;
     389
     390        bool isInFunction() const {
     391                return visitor->isInFunction();
     392        }
    373393};
    374394
  • src/AST/Pass.impl.hpp

    r4b30e8cc rc28ea4e  
    2020#include <unordered_map>
    2121
     22#include "AST/TranslationUnit.hpp"
    2223#include "AST/TypeSubstitution.hpp"
    2324
     
    167168                __pedantic_pass_assert( stmt );
    168169
     170                return stmt->accept( *this );
     171        }
     172
     173        template< typename core_t >
     174        const ast::Stmt * ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     175                __pedantic_pass_assert( __visit_children() );
     176                __pedantic_pass_assert( stmt );
     177
    169178                // add a few useful symbols to the scope
    170179                using __pass::empty;
     
    334343        }
    335344
     345        template< typename core_t >
     346        template<typename node_t, typename parent_t, typename child_t>
     347        void ast::Pass< core_t >::maybe_accept_as_compound(
     348                const node_t * & parent,
     349                child_t parent_t::*child
     350        ) {
     351                static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
     352
     353                if(__pass::skip(parent->*child)) return;
     354                const auto & old_val = __pass::get(parent->*child, 0);
     355
     356                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     357
     358                auto new_val = call_accept_as_compound( old_val );
     359
     360                static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
     361
     362                if( __pass::differs(old_val, new_val) ) {
     363                        auto new_parent = __pass::mutate<core_t>(parent);
     364                        new_parent->*child = new_val;
     365                        parent = new_parent;
     366                }
     367        }
     368
    336369
    337370        template< typename core_t >
     
    398431        pass_visitor_stats.depth--;
    399432        if ( !errors.isEmpty() ) { throw errors; }
     433}
     434
     435template< typename core_t >
     436inline void ast::accept_all( ast::TranslationUnit & unit, ast::Pass< core_t > & visitor ) {
     437        return ast::accept_all( unit.decls, visitor );
    400438}
    401439
     
    470508                                // foralls are still in function type
    471509                                maybe_accept( node, &FunctionDecl::type );
    472                                 // function body needs to have the same scope as parameters - CompoundStmt will not enter
    473                                 // a new scope if inFunction is true
     510                                // First remember that we are now within a function.
    474511                                ValueGuard< bool > oldInFunction( inFunction );
    475512                                inFunction = true;
     513                                // The function body needs to have the same scope as parameters.
     514                                // A CompoundStmt will not enter a new scope if atFunctionTop is true.
     515                                ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     516                                atFunctionTop = true;
    476517                                maybe_accept( node, &FunctionDecl::stmts );
    477518                                maybe_accept( node, &FunctionDecl::attributes );
     
    639680const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
    640681        VISIT_START( node );
    641         VISIT({
    642                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    643                 auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
    644                         if ( ! inFunctionCpy ) __pass::symtab::enter(core, 0);
    645                 }, [this, inFunctionCpy = this->inFunction]() {
    646                         if ( ! inFunctionCpy ) __pass::symtab::leave(core, 0);
     682        VISIT(
     683                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
     684                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
     685                        if ( enterScope ) __pass::symtab::enter(core, 0);
     686                }, [this, leaveScope = !this->atFunctionTop]() {
     687                        if ( leaveScope ) __pass::symtab::leave(core, 0);
    647688                });
    648                 ValueGuard< bool > guard2( inFunction );
     689                ValueGuard< bool > guard2( atFunctionTop );
     690                atFunctionTop = false;
    649691                guard_scope guard3 { *this };
    650                 inFunction = false;
    651692                maybe_accept( node, &CompoundStmt::kids );
    652         })
     693        )
    653694        VISIT_END( CompoundStmt, node );
    654695}
     
    703744                maybe_accept( node, &IfStmt::inits    );
    704745                maybe_accept( node, &IfStmt::cond     );
    705                 maybe_accept( node, &IfStmt::thenPart );
    706                 maybe_accept( node, &IfStmt::elsePart );
     746                maybe_accept_as_compound( node, &IfStmt::thenPart );
     747                maybe_accept_as_compound( node, &IfStmt::elsePart );
    707748        })
    708749
     
    721762                maybe_accept( node, &WhileStmt::inits );
    722763                maybe_accept( node, &WhileStmt::cond  );
    723                 maybe_accept( node, &WhileStmt::body  );
     764                maybe_accept_as_compound( node, &WhileStmt::body  );
    724765        })
    725766
     
    736777                // for statements introduce a level of scope (for the initialization)
    737778                guard_symtab guard { *this };
     779                // xxx - old ast does not create WithStmtsToAdd scope for loop inits. should revisit this later.
    738780                maybe_accept( node, &ForStmt::inits );
    739781                maybe_accept( node, &ForStmt::cond  );
    740782                maybe_accept( node, &ForStmt::inc   );
    741                 maybe_accept( node, &ForStmt::body  );
     783                maybe_accept_as_compound( node, &ForStmt::body  );
    742784        })
    743785
     
    834876                maybe_accept( node, &CatchStmt::decl );
    835877                maybe_accept( node, &CatchStmt::cond );
    836                 maybe_accept( node, &CatchStmt::body );
     878                maybe_accept_as_compound( node, &CatchStmt::body );
    837879        })
    838880
  • src/AST/Pass.proto.hpp

    r4b30e8cc rc28ea4e  
    2222template<typename core_t>
    2323class Pass;
     24
     25class TranslationUnit;
    2426
    2527struct PureVisitor;
  • src/AST/SymbolTable.cpp

    r4b30e8cc rc28ea4e  
    335335}
    336336
    337 /*
    338 void SymbolTable::addFunctionType( const FunctionType * ftype ) {
    339         addTypes( ftype->forall );
    340         addIds( ftype->returns );
    341         addIds( ftype->params );
    342 }
    343 */
     337
     338void SymbolTable::addFunction( const FunctionDecl * func ) {
     339        addTypes( func->type->forall );
     340        addIds( func->returns );
     341        addIds( func->params );
     342}
     343
    344344
    345345void SymbolTable::lazyInitScope() {
  • src/AST/SymbolTable.hpp

    r4b30e8cc rc28ea4e  
    145145
    146146        /// convenience function for adding all of the declarations in a function type to the indexer
    147         // void addFunctionType( const FunctionType * ftype );
     147        void addFunction( const FunctionDecl * );
    148148
    149149private:
  • src/AST/Type.cpp

    r4b30e8cc rc28ea4e  
    157157
    158158template<typename decl_t>
     159SueInstType<decl_t>::SueInstType(
     160        const base_type * b, std::vector<ptr<Expr>> && params,
     161        CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
     162: BaseInstType( b->name, std::move(params), q, std::move(as) ), base( b ) {}
     163
     164template<typename decl_t>
    159165bool SueInstType<decl_t>::isComplete() const {
    160166        return base ? base->body : false;
  • src/AST/Type.hpp

    r4b30e8cc rc28ea4e  
    302302class FunctionType final : public ParameterizedType {
    303303public:
    304 //      std::vector<ptr<DeclWithType>> returns;
    305 //      std::vector<ptr<DeclWithType>> params;
    306 
    307304        std::vector<ptr<Type>> returns;
    308305        std::vector<ptr<Type>> params;
     
    345342        : ParameterizedType(q, std::move(as)), params(), name(n) {}
    346343
     344        BaseInstType(
     345                const std::string& n, std::vector<ptr<Expr>> && params,
     346                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     347        : ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}
     348
    347349        BaseInstType( const BaseInstType & o );
    348350
     
    369371
    370372        SueInstType(
    371                 const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     373                const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     374
     375        SueInstType(
     376                const base_type * b, std::vector<ptr<Expr>> && params,
     377                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    372378
    373379        bool isComplete() const override;
  • src/AST/porting.md

    r4b30e8cc rc28ea4e  
    3030  * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0`
    3131* `PassVisitor` is replaced with `ast::Pass`
     32  * Most one shot uses can use `ast::Pass::run` and `ast::Pass::read`.
     33
     34`WithConstTypeSubstitution`
     35* `env` => `typeSubs`
    3236
    3337## Structural Changes ##
     
    146150  * allows `newObject` as just default settings
    147151
     152`FunctionDecl`
     153* `params` and `returns` added.
     154  * Contain the declarations of the parameters and return variables.
     155  * Types should match (even be shared with) the fields of `type`.
     156
    148157`NamedTypeDecl`
    149158* `parameters` => `params`
     
    154163`AggregateDecl`
    155164* `parameters` => `params`
     165
     166`StructDecl`
     167* `makeInst` replaced by better constructor on `StructInstType`.
    156168
    157169`Expr`
     
    245257* **TODO** move `kind`, `typeNames` into code generator
    246258
    247 `ReferenceToType`
     259`ReferenceToType` => `BaseInstType`
    248260* deleted `get_baseParameters()` from children
    249261  * replace with `aggr() ? aggr()->params : nullptr`
     
    261273* `returnVals` => `returns`
    262274* `parameters` => `params`
     275  * Both now just point at types.
    263276* `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
     277
     278`SueInstType`
     279* Template class, with specializations and using to implement some other types:
     280  * `StructInstType`, `UnionInstType` & `EnumInstType`
    264281
    265282`TypeInstType`
  • src/Common/PassVisitor.h

    r4b30e8cc rc28ea4e  
    354354        virtual TypeSubstitution * mutate( TypeSubstitution * sub ) final;
    355355
     356        bool isInFunction() const {
     357                return inFunction;
     358        }
     359
    356360private:
    357361        bool inFunction = false;
     362        bool atFunctionTop = false;
    358363
    359364        template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
     
    526531public:
    527532        PassVisitor<pass_type> * const visitor = nullptr;
     533
     534        bool isInFunction() const {
     535                return visitor->isInFunction();
     536        }
    528537};
    529538
  • src/Common/PassVisitor.impl.h

    r4b30e8cc rc28ea4e  
    532532                        indexerAddId( &func );
    533533                        maybeAccept_impl( node->type, *this );
    534                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    535                         // a new scope if inFunction is true
     534                        // First remember that we are now within a function.
    536535                        ValueGuard< bool > oldInFunction( inFunction );
    537536                        inFunction = true;
     537                        // The function body needs to have the same scope as parameters.
     538                        // A CompoundStmt will not enter a new scope if atFunctionTop is true.
     539                        ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     540                        atFunctionTop = true;
    538541                        maybeAccept_impl( node->statements, *this );
    539542                        maybeAccept_impl( node->attributes, *this );
     
    567570                        indexerAddId( &func );
    568571                        maybeAccept_impl( node->type, *this );
    569                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    570                         // a new scope if inFunction is true
     572                        // First remember that we are now within a function.
    571573                        ValueGuard< bool > oldInFunction( inFunction );
    572574                        inFunction = true;
     575                        // The function body needs to have the same scope as parameters.
     576                        // A CompoundStmt will not enter a new scope if atFunctionTop is true.
     577                        ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     578                        atFunctionTop = true;
    573579                        maybeAccept_impl( node->statements, *this );
    574580                        maybeAccept_impl( node->attributes, *this );
     
    601607                        indexerAddId( &func );
    602608                        maybeMutate_impl( node->type, *this );
    603                         // function body needs to have the same scope as parameters - CompoundStmt will not enter
    604                         // a new scope if inFunction is true
     609                        // First remember that we are now within a function.
    605610                        ValueGuard< bool > oldInFunction( inFunction );
    606611                        inFunction = true;
     612                        // The function body needs to have the same scope as parameters.
     613                        // A CompoundStmt will not enter a new scope if atFunctionTop is true.
     614                        ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     615                        atFunctionTop = true;
    607616                        maybeMutate_impl( node->statements, *this );
    608617                        maybeMutate_impl( node->attributes, *this );
     
    10071016        VISIT_START( node );
    10081017        {
    1009                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    1010                 ValueGuard< bool > oldInFunction( inFunction );
    1011                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
     1018                // Do not enter a new scope if atFunctionTop is true, don't leave one either.
     1019                ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     1020                auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
    10121021                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1013                 inFunction = false;
     1022                atFunctionTop = false;
    10141023                visitStatementList( node->kids );
    10151024        }
     
    10211030        VISIT_START( node );
    10221031        {
    1023                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    1024                 ValueGuard< bool > oldInFunction( inFunction );
    1025                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
     1032                // Do not enter a new scope if atFunctionTop is true, don't leave one either.
     1033                ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     1034                auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
    10261035                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1027                 inFunction = false;
     1036                atFunctionTop = false;
    10281037                visitStatementList( node->kids );
    10291038        }
     
    10351044        MUTATE_START( node );
    10361045        {
    1037                 // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    1038                 ValueGuard< bool > oldInFunction( inFunction );
    1039                 auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
     1046                // Do not enter a new scope if atFunctionTop is true, don't leave one either.
     1047                ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
     1048                auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
    10401049                auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
    1041                 inFunction = false;
     1050                atFunctionTop = false;
    10421051                mutateStatementList( node->kids );
    10431052        }
  • src/Common/utility.h

    r4b30e8cc rc28ea4e  
    360360        reverse_iterate_t( T & ref ) : ref(ref) {}
    361361
    362         typedef typename T::reverse_iterator iterator;
    363         iterator begin() { return ref.rbegin(); }
    364         iterator end() { return ref.rend(); }
     362        // this does NOT work on const T!!!
     363        // typedef typename T::reverse_iterator iterator;
     364        auto begin() { return ref.rbegin(); }
     365        auto end() { return ref.rend(); }
    365366};
    366367
  • src/Concurrency/Keywords.cc

    r4b30e8cc rc28ea4e  
    4646        }
    4747
     48        // Only detects threads constructed with the keyword thread.
     49        inline static bool isThread( DeclarationWithType * decl ) {
     50                Type * baseType = decl->get_type()->stripDeclarator();
     51                StructInstType * instType = dynamic_cast<StructInstType *>( baseType );
     52                if ( nullptr == instType ) { return false; }
     53                return instType->baseStruct->is_thread();
     54        }
     55
    4856        //=============================================================================================
    4957        // Pass declarations
     
    119127                        "get_thread",
    120128                        "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
    121                         "",
     129                        "ThreadCancelled",
    122130                        true,
    123131                        AggregateDecl::Thread
     
    290298                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first );
    291299                void validate( DeclarationWithType * );
    292                 void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    293                 void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     300                void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     301                void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
     302                void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args );
    294303
    295304                static void implement( std::list< Declaration * > & translationUnit ) {
     
    302311                StructDecl* guard_decl = nullptr;
    303312                StructDecl* dtor_guard_decl = nullptr;
     313                StructDecl* thread_guard_decl = nullptr;
    304314
    305315                static std::unique_ptr< Type > generic_func;
     
    801811                bool first = false;
    802812                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first );
    803                 bool isDtor = CodeGen::isDestructor( decl->name );
     813                bool const isDtor = CodeGen::isDestructor( decl->name );
    804814
    805815                // Is this function relevant to monitors
     
    849859
    850860                // Instrument the body
    851                 if( isDtor ) {
    852                         addDtorStatments( decl, body, mutexArgs );
     861                if ( isDtor && isThread( mutexArgs.front() ) ) {
     862                        if( !thread_guard_decl ) {
     863                                SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" );
     864                        }
     865                        addThreadDtorStatements( decl, body, mutexArgs );
     866                }
     867                else if ( isDtor ) {
     868                        addDtorStatements( decl, body, mutexArgs );
    853869                }
    854870                else {
    855                         addStatments( decl, body, mutexArgs );
     871                        addStatements( decl, body, mutexArgs );
    856872                }
    857873        }
     
    870886                        assert( !dtor_guard_decl );
    871887                        dtor_guard_decl = decl;
     888                }
     889                else if( decl->name == "thread_dtor_guard_t" && decl->body ) {
     890                        assert( !thread_guard_decl );
     891                        thread_guard_decl = decl;
    872892                }
    873893        }
     
    908928        }
    909929
    910         void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     930        void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    911931                Type * arg_type = args.front()->get_type()->clone();
    912932                arg_type->set_mutex( false );
     
    957977
    958978                //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) };
    959                 body->push_front( new DeclStmt( monitors) );
    960         }
    961 
    962         void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     979                body->push_front( new DeclStmt( monitors ) );
     980        }
     981
     982        void MutexKeyword::addThreadDtorStatements(
     983                        FunctionDecl*, CompoundStmt * body,
     984                        const std::list<DeclarationWithType * > & args ) {
     985                assert( args.size() == 1 );
     986                DeclarationWithType * arg = args.front();
     987                Type * arg_type = arg->get_type()->clone();
     988                assert( arg_type->get_mutex() );
     989                arg_type->set_mutex( false );
     990
     991                // thread_dtor_guard_t __guard = { this, intptr( 0 ) };
     992                body->push_front(
     993                        new DeclStmt( new ObjectDecl(
     994                                "__guard",
     995                                noStorageClasses,
     996                                LinkageSpec::Cforall,
     997                                nullptr,
     998                                new StructInstType(
     999                                        noQualifiers,
     1000                                        thread_guard_decl
     1001                                ),
     1002                                new ListInit(
     1003                                        {
     1004                                                new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ),
     1005                                                new SingleInit( new UntypedExpr(
     1006                                                        new NameExpr( "intptr" ), {
     1007                                                                new ConstantExpr( Constant::from_int( 0 ) ),
     1008                                                        }
     1009                                                ) ),
     1010                                        },
     1011                                        noDesignators,
     1012                                        true
     1013                                )
     1014                        ))
     1015                );
     1016        }
     1017
     1018        void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
    9631019                ObjectDecl * monitors = new ObjectDecl(
    9641020                        "__monitors",
  • src/GenPoly/GenPoly.cc

    r4b30e8cc rc28ea4e  
    4646                }
    4747
     48                bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env) {
     49                        for (auto &param : params) {
     50                                auto paramType = param.strict_as<ast::TypeExpr>();
     51                                if (isPolyType(paramType->type, env)) return true;
     52                        }
     53                        return false;
     54                }
     55
    4856                /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present
    4957                bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
     
    5664                }
    5765
     66                bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TyVarMap & tyVars, const ast::TypeSubstitution * env) {
     67                        for (auto &param : params) {
     68                                auto paramType = param.strict_as<ast::TypeExpr>();
     69                                if (isPolyType(paramType->type, tyVars, env)) return true;
     70                        }
     71                        return false;
     72                }
     73
    5874                /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present
    5975                bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
     
    92108                        Type *newType = env->lookup( typeInst->get_name() );
    93109                        if ( newType ) return newType;
     110                }
     111                return type;
     112        }
     113
     114        const ast::Type * replaceTypeInst(const ast::Type * type, const ast::TypeSubstitution * env) {
     115                if (!env) return type;
     116                if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) {
     117                        auto newType = env->lookup(typeInst->name);
     118                        if (newType) return newType;
    94119                }
    95120                return type;
     
    111136        }
    112137
     138        const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env) {
     139                type = replaceTypeInst( type, env );
     140
     141                if ( dynamic_cast< const ast::TypeInstType * >( type ) ) {
     142                        return type;
     143                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
     144                        return isPolyType( arrayType->base, env );
     145                } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) {
     146                        if ( hasPolyParams( structType->params, env ) ) return type;
     147                } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) {
     148                        if ( hasPolyParams( unionType->params, env ) ) return type;
     149                }
     150                return 0;
     151        }
     152
    113153        Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    114154                type = replaceTypeInst( type, env );
     
    126166                }
    127167                return 0;
     168        }
     169
     170        const ast::Type * isPolyType(const ast::Type * type, const TyVarMap & tyVars, const ast::TypeSubstitution * env) {
     171                type = replaceTypeInst( type, env );
     172
     173                if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
     174                        return tyVars.find(typeInst->name) != tyVars.end() ? type : nullptr;
     175                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
     176                        return isPolyType( arrayType->base, env );
     177                } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) {
     178                        if ( hasPolyParams( structType->params, env ) ) return type;
     179                } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) {
     180                        if ( hasPolyParams( unionType->params, env ) ) return type;
     181                }
     182                return nullptr;
    128183        }
    129184
     
    449504        }
    450505
     506        namespace {
     507                // temporary hack to avoid re-implementing anything related to TyVarMap
     508                // does this work? these two structs have identical definitions.
     509                inline TypeDecl::Data convData(const ast::TypeDecl::Data & data) {
     510                        return *reinterpret_cast<const TypeDecl::Data *>(&data);
     511                }
     512        }
     513
    451514        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
    452515                // is parameter is not polymorphic, don't need to box
     
    459522        }
    460523
     524        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TyVarMap &exprTyVars, const ast::TypeSubstitution * env) {
     525                // is parameter is not polymorphic, don't need to box
     526                if ( ! isPolyType( param, exprTyVars ) ) return false;
     527                ast::ptr<ast::Type> newType = arg;
     528                if ( env ) env->apply( newType );
     529                // if the argument's type is polymorphic, we don't need to box again!
     530                return ! isPolyType( newType );
     531        }
     532
    461533        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
    462534                FunctionType * function = getFunctionType( appExpr->function->result );
     
    467539        }
    468540
     541        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * appExpr, const ast::TypeSubstitution * env) {
     542                const ast::FunctionType * function = getFunctionType(appExpr->func->result);
     543                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->func->result ).c_str() );
     544                TyVarMap exprTyVars(TypeDecl::Data{});
     545                makeTyVarMap(function, exprTyVars);
     546                return needsBoxing(param, arg, exprTyVars, env);
     547
     548        }
     549
    469550        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    470551                tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );
     552        }
     553
     554        void addToTyVarMap( const ast::TypeDecl * tyVar, TyVarMap & tyVarMap) {
     555                tyVarMap.insert(tyVar->name, convData(ast::TypeDecl::Data{tyVar}));
    471556        }
    472557
     
    478563                if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
    479564                        makeTyVarMap( pointer->get_base(), tyVarMap );
     565                }
     566        }
     567
     568        void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap) {
     569                if (auto ptype = dynamic_cast<const ast::ParameterizedType *>(type)) {
     570                        for (auto & tyVar : ptype->forall) {
     571                                assert (tyVar);
     572                                addToTyVarMap(tyVar, tyVarMap);
     573                        }
     574                }
     575                if (auto pointer = dynamic_cast<const ast::PointerType *>(type)) {
     576                        makeTyVarMap(pointer->base, tyVarMap);
    480577                }
    481578        }
  • src/GenPoly/GenPoly.h

    r4b30e8cc rc28ea4e  
    2626
    2727namespace GenPoly {
     28
    2829        typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
    29 
    3030        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    3131        Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
     
    3333        /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
    3434        Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );
     35        const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr);
    3536
    3637        /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
    3738        Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
     39        const ast::Type * isPolyType(const ast::Type * type, const TyVarMap & tyVars, const ast::TypeSubstitution * env = nullptr);
    3840
    3941        /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
     
    8486        /// true if arg requires boxing given exprTyVars
    8587        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );
     88        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TyVarMap &exprTyVars, const ast::TypeSubstitution * env);
    8689
    8790        /// true if arg requires boxing in the call to appExpr
    8891        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );
     92        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * appExpr, const ast::TypeSubstitution * env);
    8993
    9094        /// Adds the type variable `tyVar` to `tyVarMap`
     
    9397        /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
    9498        void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
     99        void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap);
    95100
    96101        /// Prints type variable map
  • src/GenPoly/Specialize.cc

    r4b30e8cc rc28ea4e  
    218218                thunkFunc->get_attributes().push_back( new Attribute( "unused" ) );
    219219
     220                // Thunks at the global level must be static to avoid collisions between files.
     221                // (Conversly thunks inside a function must be unique and not static.)
     222                thunkFunc->storageClasses.is_static = !isInFunction();
     223
    220224                // thread thunk parameters into call to actual function, naming thunk parameters as we go
    221225                UniqueName paramNamer( paramPrefix );
  • src/InitTweak/FixGlobalInit.cc

    r4b30e8cc rc28ea4e  
    3434#include "SynTree/Visitor.h"       // for acceptAll, Visitor
    3535
     36#include "AST/Expr.hpp"
     37#include "AST/Node.hpp"
     38#include "AST/Pass.hpp"
     39
    3640namespace InitTweak {
    3741        class GlobalFixer : public WithShortCircuiting {
     
    5054                FunctionDecl * initFunction;
    5155                FunctionDecl * destroyFunction;
     56        };
     57
     58        class GlobalFixer_new : public ast::WithShortCircuiting {
     59        public:
     60                void previsit (const ast::ObjectDecl *);
     61                void previsit (const ast::FunctionDecl *) { visit_children = false; }
     62                void previsit (const ast::StructDecl *) { visit_children = false; }
     63                void previsit (const ast::UnionDecl *) { visit_children = false; }
     64                void previsit (const ast::EnumDecl *) { visit_children = false; }
     65                void previsit (const ast::TraitDecl *) { visit_children = false; }
     66                void previsit (const ast::TypeDecl *) { visit_children = false; }
     67
     68                std::list< ast::ptr<ast::Stmt> > initStmts;
     69                std::list< ast::ptr<ast::Stmt> > destroyStmts;
    5270        };
    5371
     
    91109        }
    92110
     111        void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
     112                ast::Pass<GlobalFixer_new> fixer;
     113                accept_all(translationUnit, fixer);
     114
     115                if ( !fixer.core.initStmts.empty() ) {
     116                        std::vector<ast::ptr<ast::Expr>> ctorParams;
     117                        if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
     118                        auto initFunction = new ast::FunctionDecl({}, "__global_init__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.initStmts)),
     119                                ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("constructor", std::move(ctorParams))});
     120
     121                        translationUnit.decls.emplace_back( initFunction );
     122                } // if
     123
     124                if ( !fixer.core.destroyStmts.empty() ) {
     125                        std::vector<ast::ptr<ast::Expr>> dtorParams;
     126                        if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
     127                        auto destroyFunction = new ast::FunctionDecl({}, "__global_destroy__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.destroyStmts)),
     128                                ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("destructor", std::move(dtorParams))});
     129
     130                        translationUnit.decls.emplace_back(destroyFunction);
     131                } // if
     132        }
     133
    93134        void GlobalFixer::previsit( ObjectDecl *objDecl ) {
    94135                std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
     
    112153                        } // if
    113154                        if ( Statement * ctor = ctorInit->ctor ) {
    114                                 // Translation 1: Add this attribute on the global declaration:
    115                                 //    __attribute__((section (".data#")))
    116                                 // which makes gcc put the global in the data section,
    117                                 // so that the global is writeable (via a const cast) in the init function.
    118                                 // The trailing # is an injected assembly comment, to suppress the "a" in
    119                                 //    .section .data,"a"
    120                                 //    .section .data#,"a"
    121                                 // to avoid assembler warning "ignoring changed section attributes for .data"
    122                                 Type *strLitT = new PointerType( Type::Qualifiers( ),
    123                                         new BasicType( Type::Qualifiers( ), BasicType::Char ) );
    124                                 std::list< Expression * > attr_params;
    125                                 attr_params.push_back(
    126                                         new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
    127                                 objDecl->attributes.push_back(new Attribute("section", attr_params));
    128                                 // Translation 2: Move the initizliation off the global declaration,
    129                                 // into the startup function.
     155                                addDataSectonAttribute( objDecl );
    130156                                initStatements.push_back( ctor );
    131157                                objDecl->init = nullptr;
     
    142168        }
    143169
     170        void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) {
     171                auto mutDecl = mutate(objDecl);
     172                assertf(mutDecl == objDecl, "Global object decl must be unique");
     173                if ( auto ctorInit = objDecl->init.as<ast::ConstructorInit>() ) {
     174                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     175                        assert( ! ctorInit->ctor || ! ctorInit->init );
     176
     177                        const ast::Stmt * dtor = ctorInit->dtor;
     178                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
     179                                // don't need to call intrinsic dtor, because it does nothing, but
     180                                // non-intrinsic dtors must be called
     181                                destroyStmts.push_front( dtor );
     182                                // ctorInit->dtor = nullptr;
     183                        } // if
     184                        if ( const ast::Stmt * ctor = ctorInit->ctor ) {
     185                                initStmts.push_back( ctor );
     186                                mutDecl->init = nullptr;
     187                                // ctorInit->ctor = nullptr;
     188                        } else if ( const ast::Init * init = ctorInit->init ) {
     189                                mutDecl->init = init;
     190                                // ctorInit->init = nullptr;
     191                        } else {
     192                                // no constructor and no initializer, which is okay
     193                                mutDecl->init = nullptr;
     194                        } // if
     195                        // delete ctorInit;
     196                } // if
     197        }
     198
    144199        // only modify global variables
    145200        void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; }
  • src/InitTweak/FixGlobalInit.h

    r4b30e8cc rc28ea4e  
    1919#include <string>  // for string
    2020
     21#include <AST/Fwd.hpp>
     22
     23
    2124class Declaration;
    2225
     
    2629        /// function is for library code.
    2730        void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary );
     31        void fixGlobalInit( ast::TranslationUnit & translationUnit, bool inLibrary );
    2832} // namespace
    2933
  • src/InitTweak/FixInit.cc

    r4b30e8cc rc28ea4e  
    219219                };
    220220
    221                 struct SplitExpressions : public WithShortCircuiting, public WithTypeSubstitution, public WithStmtsToAdd {
     221                struct SplitExpressions : public WithShortCircuiting, /*public WithTypeSubstitution, */public WithStmtsToAdd {
    222222                        /// add CompoundStmts around top-level expressions so that temporaries are destroyed in the correct places.
    223223                        static void split( std::list< Declaration * > &translationUnit );
     
    802802                                if ( Statement * ctor = ctorInit->get_ctor() ) {
    803803                                        if ( objDecl->get_storageClasses().is_static ) {
     804
     805                                                // The ojbect needs to go in the data section, regardless of dtor complexity below.
     806                                                // The attribute works, and is meant to apply, both for leaving the static local alone,
     807                                                // and for hoisting it out as a static global.
     808                                                addDataSectonAttribute( objDecl );
     809
    804810                                                // originally wanted to take advantage of gcc nested functions, but
    805811                                                // we get memory errors with this approach. To remedy this, the static
  • src/InitTweak/FixInit.h

    r4b30e8cc rc28ea4e  
    2020
    2121class Declaration;
     22namespace ast {
     23        class TranslationUnit;
     24}
    2225
    2326namespace InitTweak {
    2427        /// replace constructor initializers with expression statements and unwrap basic C-style initializers
    2528        void fix( std::list< Declaration * > & translationUnit, bool inLibrary );
     29
     30        void fix( ast::TranslationUnit & translationUnit, bool inLibrary);
    2631} // namespace
    2732
  • src/InitTweak/GenInit.cc

    r4b30e8cc rc28ea4e  
    283283                assert( stmts.size() <= 1 );
    284284                return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr;
     285
     286        }
     287
     288        ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
     289                assertf(objDecl, "genCtorDtor passed null objDecl");
     290                InitExpander_new srcParam(arg);
     291                return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl);
    285292        }
    286293
  • src/InitTweak/GenInit.h

    r4b30e8cc rc28ea4e  
    3333        /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
    3434        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
     35        ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);
    3536
    3637        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
  • src/InitTweak/InitTweak.cc

    r4b30e8cc rc28ea4e  
    498498        }
    499499
     500        const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) {
     501                assertf( func, "getParamThis: nullptr ftype" );
     502                auto & params = func->params;
     503                assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str());
     504                return params.front().strict_as<ast::ObjectDecl>();
     505        }
     506
    500507        bool tryConstruct( DeclarationWithType * dwt ) {
    501508                ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
     
    511518        }
    512519
     520        bool tryConstruct( const ast::DeclWithType * dwt ) {
     521                auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt );
     522                if ( ! objDecl ) return false;
     523                return (objDecl->init == nullptr ||
     524                                ( objDecl->init != nullptr && objDecl->init->maybeConstructed ))
     525                        && ! objDecl->storage.is_extern
     526                        && isConstructable( objDecl->type );
     527        }
     528
     529        bool isConstructable( const ast::Type * type ) {
     530                return ! dynamic_cast< const ast::VarArgsType * >( type ) && ! dynamic_cast< const ast::ReferenceType * >( type )
     531                && ! dynamic_cast< const ast::FunctionType * >( type ) && ! Tuples::isTtype( type );
     532        }
     533
    513534        struct CallFinder_old {
    514535                CallFinder_old( const std::list< std::string > & names ) : names( names ) {}
     
    536557
    537558        struct CallFinder_new final {
    538                 std::vector< ast::ptr< ast::Expr > > matches;
     559                std::vector< const ast::Expr * > matches;
    539560                const std::vector< std::string > names;
    540561
     
    558579        }
    559580
    560         std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt ) {
     581        std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) {
    561582                ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
    562583                maybe_accept( stmt, finder );
     
    696717                template <typename Predicate>
    697718                bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
    698                         std::vector< ast::ptr< ast::Expr > > callExprs = collectCtorDtorCalls( stmt );
     719                        std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt );
    699720                        return std::all_of( callExprs.begin(), callExprs.end(), pred );
    700721                }
     
    939960        }
    940961
     962        // looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards
     963        // following passes may accidentally resolve this expression if returned as untyped...
     964        ast::Expr * createBitwiseAssignment (const ast::Expr * dst, const ast::Expr * src) {
     965                static ast::ptr<ast::FunctionDecl> assign = nullptr;
     966                if (!assign) {
     967                        auto td = new ast::TypeDecl({}, "T", {}, nullptr, ast::TypeDecl::Dtype, true);
     968                        assign = new ast::FunctionDecl({}, "?=?", {},
     969                        { new ast::ObjectDecl({}, "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))),
     970                          new ast::ObjectDecl({}, "_src", new ast::TypeInstType("T", td))},
     971                        { new ast::ObjectDecl({}, "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic);
     972                }
     973                if (dst->result.as<ast::ReferenceType>()) {
     974                        for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
     975                                dst = new ast::AddressExpr(dst);
     976                        }
     977                }
     978                else {
     979                        dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {}));
     980                }
     981                if (src->result.as<ast::ReferenceType>()) {
     982                        for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
     983                                src = new ast::AddressExpr(src);
     984                        }
     985                }
     986                return new ast::ApplicationExpr(dst->location, ast::VariableExpr::functionPointer(dst->location, assign), {dst, src});
     987        }
     988
    941989        struct ConstExprChecker : public WithShortCircuiting {
    942990                // most expressions are not const expr
     
    10551103                return isCopyFunction( decl, "?{}" );
    10561104        }
     1105
     1106        void addDataSectonAttribute( ObjectDecl * objDecl ) {
     1107                Type *strLitT = new PointerType( Type::Qualifiers( ),
     1108                        new BasicType( Type::Qualifiers( ), BasicType::Char ) );
     1109                std::list< Expression * > attr_params;
     1110                attr_params.push_back(
     1111                        new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
     1112                objDecl->attributes.push_back(new Attribute("section", attr_params));
     1113        }
     1114
    10571115}
  • src/InitTweak/InitTweak.h

    r4b30e8cc rc28ea4e  
    3838        /// returns the first parameter of a constructor/destructor/assignment function
    3939        ObjectDecl * getParamThis( FunctionType * ftype );
     40        const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func);
    4041
    4142        /// generate a bitwise assignment operation.
    4243        ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src );
     44
     45        ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src);
    4346
    4447        /// transform Initializer into an argument list that can be passed to a call expression
     
    4851        /// True if the resolver should try to construct dwt
    4952        bool tryConstruct( DeclarationWithType * dwt );
     53        bool tryConstruct( const ast::DeclWithType * dwt );
    5054
    5155        /// True if the type can have a user-defined constructor
    5256        bool isConstructable( Type * t );
     57        bool isConstructable( const ast::Type * t );
    5358
    5459        /// True if the Initializer contains designations
     
    7984        /// get all Ctor/Dtor call expressions from a Statement
    8085        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    81         std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt );
     86        std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt );
    8287
    8388        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     
    102107        bool isConstExpr( Expression * expr );
    103108        bool isConstExpr( Initializer * init );
     109
     110        /// Modifies objDecl to have:
     111        ///    __attribute__((section (".data#")))
     112        /// which makes gcc put the declared variable in the data section,
     113        /// which is helpful for global constants on newer gcc versions,
     114        /// so that CFA's generated initialization won't segfault when writing it via a const cast.
     115        /// The trailing # is an injected assembly comment, to suppress the "a" in
     116        ///    .section .data,"a"
     117        ///    .section .data#,"a"
     118        /// to avoid assembler warning "ignoring changed section attributes for .data"
     119        void addDataSectonAttribute( ObjectDecl * objDecl );
    104120
    105121        class InitExpander_old {
  • src/InitTweak/module.mk

    r4b30e8cc rc28ea4e  
    2323        InitTweak/GenInit.h \
    2424        InitTweak/InitTweak.cc \
    25         InitTweak/InitTweak.h
     25        InitTweak/InitTweak.h \
     26        InitTweak/FixInitNew.cpp
    2627
    2728SRCDEMANGLE += \
  • src/Parser/ParseNode.h

    r4b30e8cc rc28ea4e  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jul  6 09:33:32 2020
    13 // Update Count     : 892
     12// Last Modified On : Sat Oct 24 03:53:54 2020
     13// Update Count     : 895
    1414//
    1515
     
    205205struct TypeData;
    206206
    207 class DeclarationNode : public ParseNode {
    208   public:
     207struct DeclarationNode : public ParseNode {
    209208        // These enumerations must harmonize with their names in DeclarationNode.cc.
    210209        enum BasicType { Void, Bool, Char, Int, Int128,
     
    304303        bool get_inLine() const { return inLine; }
    305304        DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }
    306   public:
     305
    307306        DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
    308307
     
    360359//##############################################################################
    361360
    362 class StatementNode final : public ParseNode {
    363   public:
     361struct StatementNode final : public ParseNode {
    364362        StatementNode() { stmt = nullptr; }
    365363        StatementNode( Statement * stmt ) : stmt( stmt ) {}
     
    382380                os << stmt.get() << std::endl;
    383381        }
    384   private:
     382
    385383        std::unique_ptr<Statement> stmt;
    386384}; // StatementNode
     
    426424Statement * build_finally( StatementNode * stmt );
    427425Statement * build_compound( StatementNode * first );
     426StatementNode * maybe_build_compound( StatementNode * first );
    428427Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
    429428Statement * build_directive( std::string * directive );
  • src/Parser/StatementNode.cc

    r4b30e8cc rc28ea4e  
    1010// Created On       : Sat May 16 14:59:41 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  4 09:39:25 2018
    13 // Update Count     : 363
     12// Last Modified On : Sat Oct 24 04:20:55 2020
     13// Update Count     : 383
    1414//
    1515
     
    345345} // build_compound
    346346
     347// A single statement in a control structure is always converted to a compound statement so subsequent generated code
     348// can be placed within this compound statement. Otherwise, code generation has to constantly check for a single
     349// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
     350// conical form for code generation.
     351StatementNode * maybe_build_compound( StatementNode * first ) {
     352        // Optimization: if the control-structure statement is a compound statement, do not wrap it.
     353        // e.g., if (...) {...} do not wrap the existing compound statement.
     354        if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
     355                CompoundStmt * cs = new CompoundStmt();
     356                buildMoveList( first, cs->get_kids() );
     357                return new StatementNode( cs );
     358        } // if
     359        return first;
     360} // maybe_build_compound
     361
    347362Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
    348363        std::list< Expression * > out, in;
  • src/Parser/parser.yy

    r4b30e8cc rc28ea4e  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct  9 18:09:09 2020
    13 // Update Count     : 4614
     12// Last Modified On : Sat Oct 24 08:21:14 2020
     13// Update Count     : 4624
    1414//
    1515
     
    10801080        IF '(' if_control_expression ')' statement                      %prec THEN
    10811081                // explicitly deal with the shift/reduce conflict on if/else
    1082                 { $$ = new StatementNode( build_if( $3, $5, nullptr ) ); }
     1082                { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); }
    10831083        | IF '(' if_control_expression ')' statement ELSE statement
    1084                 { $$ = new StatementNode( build_if( $3, $5, $7 ) ); }
     1084                { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); }
    10851085        ;
    10861086
     
    11301130
    11311131case_clause:                                                                                    // CFA
    1132         case_label_list statement                                       { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }
     1132        case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }
    11331133        ;
    11341134
     
    11481148iteration_statement:
    11491149        WHILE '(' push if_control_expression ')' statement pop
    1150                 { $$ = new StatementNode( build_while( $4, $6 ) ); }
     1150                { $$ = new StatementNode( build_while( $4, maybe_build_compound( $6 ) ) ); }
    11511151        | WHILE '(' ')' statement                                                       // CFA => while ( 1 )
    1152                 { $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), $4 ) ); }
     1152                { $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
    11531153        | DO statement WHILE '(' comma_expression ')' ';'
    1154                 { $$ = new StatementNode( build_do_while( $5, $2 ) ); }
     1154                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    11551155        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    1156                 { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), $2 ) ); }
     1156                { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
    11571157        | FOR '(' push for_control_expression_list ')' statement pop
    1158                 { $$ = new StatementNode( build_for( $4, $6 ) ); }
     1158                { $$ = new StatementNode( build_for( $4, maybe_build_compound( $6 ) ) ); }
    11591159        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
    1160                 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), $4 ) ); }
     1160                { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
    11611161        ;
    11621162
     
    13411341waitfor_clause:
    13421342        when_clause_opt waitfor statement                                       %prec THEN
    1343                 { $$ = build_waitfor( $2, $3, $1 ); }
     1343                { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); }
    13441344        | when_clause_opt waitfor statement WOR waitfor_clause
    1345                 { $$ = build_waitfor( $2, $3, $1, $5 ); }
     1345                { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); }
    13461346        | when_clause_opt timeout statement                                     %prec THEN
    1347                 { $$ = build_waitfor_timeout( $2, $3, $1 ); }
     1347                { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); }
    13481348        | when_clause_opt ELSE statement
    1349                 { $$ = build_waitfor_timeout( nullptr, $3, $1 ); }
     1349                { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
    13501350                // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    13511351        | when_clause_opt timeout statement WOR ELSE statement
    13521352                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    13531353        | when_clause_opt timeout statement WOR when_clause ELSE statement
    1354                 { $$ = build_waitfor_timeout( $2, $3, $1, $7, $5 ); }
     1354                { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5 ); }
    13551355        ;
    13561356
  • src/ResolvExpr/Resolver.cc

    r4b30e8cc rc28ea4e  
    11051105                }
    11061106
    1107                 /// Establish post-resolver invariants for expressions
     1107               
     1108        } // anonymous namespace
     1109/// Establish post-resolver invariants for expressions
    11081110                void finishExpr(
    11091111                        ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
     
    11181120                        StripCasts_new::strip( expr );
    11191121                }
    1120         } // anonymous namespace
    1121 
    11221122
    11231123        ast::ptr< ast::Expr > resolveInVoidContext(
     
    11391139        }
    11401140
    1141         namespace {
    1142                 /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
     1141        /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    11431142                /// context.
    11441143                ast::ptr< ast::Expr > findVoidExpression(
     
    11511150                        return newExpr;
    11521151                }
     1152
     1153        namespace {
     1154               
    11531155
    11541156                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
     
    11621164                        CandidateRef choice =
    11631165                                findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
    1164                         finishExpr( choice->expr, choice->env, untyped->env );
     1166                        ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
    11651167                        return std::move( choice->expr );
    11661168                }
     
    12721274        // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
    12731275
    1274         void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
     1276        void resolve( ast::TranslationUnit& translationUnit ) {
    12751277                ast::Pass< Resolver_new >::run( translationUnit );
    12761278        }
  • src/ResolvExpr/Resolver.h

    r4b30e8cc rc28ea4e  
    3535        class StmtExpr;
    3636        class SymbolTable;
     37        class TranslationUnit;
    3738        class Type;
    3839        class TypeEnvironment;
     
    5556
    5657        /// Checks types and binds syntactic constructs to typed representations
    57         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
     58        void resolve( ast::TranslationUnit& translationUnit );
    5859        /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    5960        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr );
     
    6667        ast::ptr< ast::Expr > findSingleExpression(
    6768                const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
     69        ast::ptr< ast::Expr > findVoidExpression(
     70                const ast::Expr * untyped, const ast::SymbolTable & symtab);
    6871        /// Resolves a constructor init expression
    69         ast::ptr< ast::Init > resolveCtorInit( 
     72        ast::ptr< ast::Init > resolveCtorInit(
    7073                const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
    7174        /// Resolves a statement expression
    72         ast::ptr< ast::Expr > resolveStmtExpr( 
     75        ast::ptr< ast::Expr > resolveStmtExpr(
    7376                const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
    7477} // namespace ResolvExpr
  • src/SymTab/Autogen.cc

    r4b30e8cc rc28ea4e  
    233233        }
    234234
     235        // shallow copy the pointer list for return
     236        std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {
     237                if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {
     238                        return structInst->base->params;
     239                }
     240                if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {
     241                        return unionInst->base->params;
     242                }
     243                return {};
     244        }
     245
    235246        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    236247        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
     
    244255                ftype->parameters.push_back( dstParam );
    245256                return ftype;
     257        }
     258
     259        ///
     260        ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {
     261                std::vector<ast::ptr<ast::TypeDecl>> typeParams;
     262                if (maybePolymorphic) typeParams = getGenericParams(paramType);
     263                auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);
     264                return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc));
    246265        }
    247266
  • src/SymTab/Autogen.h

    r4b30e8cc rc28ea4e  
    5555        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    5656        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
     57
     58        ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);
    5759
    5860        /// generate the type of a copy constructor for paramType.
  • src/SynTree/Expression.h

    r4b30e8cc rc28ea4e  
    163163};
    164164
     165/// VariableExpr represents an expression that simply refers to the value of a named variable.
     166/// Does not take ownership of var.
     167class VariableExpr : public Expression {
     168  public:
     169        DeclarationWithType * var;
     170
     171        VariableExpr();
     172        VariableExpr( DeclarationWithType * var );
     173        VariableExpr( const VariableExpr & other );
     174        virtual ~VariableExpr();
     175
     176        bool get_lvalue() const final;
     177
     178        DeclarationWithType * get_var() const { return var; }
     179        void set_var( DeclarationWithType * newValue ) { var = newValue; }
     180
     181        static VariableExpr * functionPointer( FunctionDecl * decl );
     182
     183        virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
     184        virtual void accept( Visitor & v ) override { v.visit( this ); }
     185        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     186        virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     187        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     188};
     189
    165190// The following classes are used to represent expression types that cannot be converted into
    166191// function-call format.
     
    329354};
    330355
    331 /// VariableExpr represents an expression that simply refers to the value of a named variable.
    332 /// Does not take ownership of var.
    333 class VariableExpr : public Expression {
    334   public:
    335         DeclarationWithType * var;
    336 
    337         VariableExpr();
    338         VariableExpr( DeclarationWithType * var );
    339         VariableExpr( const VariableExpr & other );
    340         virtual ~VariableExpr();
    341 
    342         bool get_lvalue() const final;
    343 
    344         DeclarationWithType * get_var() const { return var; }
    345         void set_var( DeclarationWithType * newValue ) { var = newValue; }
    346 
    347         static VariableExpr * functionPointer( FunctionDecl * decl );
    348 
    349         virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
    350         virtual void accept( Visitor & v ) override { v.visit( this ); }
    351         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    352         virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    353         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    354 };
    355 
    356356/// ConstantExpr represents an expression that simply refers to the value of a constant
    357357class ConstantExpr : public Expression {
  • src/main.cc

    r4b30e8cc rc28ea4e  
    343343                        auto transUnit = convert( move( translationUnit ) );
    344344                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
     345                        if ( exprp ) {
     346                                translationUnit = convert( move( transUnit ) );
     347                                dump( translationUnit );
     348                                return EXIT_SUCCESS;
     349                        } // if
     350
     351                        PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
    345352                        translationUnit = convert( move( transUnit ) );
    346353                } else {
    347354                        PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     355                        if ( exprp ) {
     356                                dump( translationUnit );
     357                                return EXIT_SUCCESS;
     358                        }
     359
     360                        PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
    348361                }
    349362
    350                 if ( exprp ) {
    351                         dump( translationUnit );
    352                         return EXIT_SUCCESS;
    353                 } // if
    354 
    355363                // fix ObjectDecl - replaces ConstructorInit nodes
    356                 PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
    357364                if ( ctorinitp ) {
    358365                        dump ( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.