Changeset eef8dfb for src/InitTweak


Ignore:
Timestamp:
Jan 7, 2021, 2:55:57 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
Children:
58fe85a
Parents:
bdfc032 (diff), 44e37ef (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' into dkobets-vector

Location:
src/InitTweak
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixGlobalInit.cc

    rbdfc032 reef8dfb  
    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 ) {
     155                                addDataSectonAttribute( objDecl );
    114156                                initStatements.push_back( ctor );
    115157                                objDecl->init = nullptr;
     
    126168        }
    127169
     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                                addDataSectionAttribute(mutDecl);
     186                                initStmts.push_back( ctor );
     187                                mutDecl->init = nullptr;
     188                                // ctorInit->ctor = nullptr;
     189                        } else if ( const ast::Init * init = ctorInit->init ) {
     190                                mutDecl->init = init;
     191                                // ctorInit->init = nullptr;
     192                        } else {
     193                                // no constructor and no initializer, which is okay
     194                                mutDecl->init = nullptr;
     195                        } // if
     196                        // delete ctorInit;
     197                } // if
     198        }
     199
    128200        // only modify global variables
    129201        void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; }
  • src/InitTweak/FixGlobalInit.h

    rbdfc032 reef8dfb  
    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

    rbdfc032 reef8dfb  
    1010// Created On       : Wed Jan 13 16:29:30 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:41:27 2019
    13 // Update Count     : 77
     12// Last Modified On : Sun Feb 16 04:17:07 2020
     13// Update Count     : 82
    1414//
    1515#include "FixInit.h"
     
    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 );
     
    745745                }
    746746
    747                 // to prevent warnings (‘_unq0’ may be used uninitialized in this function),
     747                // to prevent warnings ('_unq0' may be used uninitialized in this function),
    748748                // insert an appropriate zero initializer for UniqueExpr temporaries.
    749749                Initializer * makeInit( Type * t ) {
     
    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

    rbdfc032 reef8dfb  
    1010// Created On       : Wed Jan 13 16:29:30 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:31:06 2017
    13 // Update Count     : 6
     12// Last Modified On : Sun Feb 16 07:54:50 2020
     13// Update Count     : 8
    1414//
    1515
     
    2020
    2121class Declaration;
     22namespace ast {
     23        struct TranslationUnit;
     24}
    2225
    2326namespace InitTweak {
    24   /// replace constructor initializers with expression statements
    25   /// and unwrap basic C-style initializers
     27        /// replace constructor initializers with expression statements and unwrap basic C-style initializers
    2628        void fix( std::list< Declaration * > & translationUnit, bool inLibrary );
     29
     30        void fix( ast::TranslationUnit & translationUnit, bool inLibrary);
    2731} // namespace
    2832
  • src/InitTweak/GenInit.cc

    rbdfc032 reef8dfb  
    2626#include "AST/Node.hpp"
    2727#include "AST/Stmt.hpp"
     28#include "CompilationState.h"
    2829#include "CodeGen/OperatorTable.h"
    2930#include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
     
    121122        };
    122123
     124        struct HoistArrayDimension_NoResolve final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
     125                /// hoist dimension from array types in object declaration so that it uses a single
     126                /// const variable of type size_t, so that side effecting array dimensions are only
     127                /// computed once.
     128                static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
     129
     130                void premutate( ObjectDecl * objectDecl );
     131                DeclarationWithType * postmutate( ObjectDecl * objectDecl );
     132                void premutate( FunctionDecl *functionDecl );
     133                // should not traverse into any of these declarations to find objects
     134                // that need to be constructed or destructed
     135                void premutate( AggregateDecl * ) { visit_children = false; }
     136                void premutate( NamedTypeDecl * ) { visit_children = false; }
     137                void premutate( FunctionType * ) { visit_children = false; }
     138
     139                void hoist( Type * type );
     140
     141                Type::StorageClasses storageClasses;
     142                bool inFunction = false;
     143        };
     144
    123145        void genInit( std::list< Declaration * > & translationUnit ) {
     146                if (!useNewAST) {
     147                        HoistArrayDimension::hoistArrayDimension( translationUnit );
     148                }
     149                else {
     150                        HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit );
     151                }
    124152                fixReturnStatements( translationUnit );
    125                 HoistArrayDimension::hoistArrayDimension( translationUnit );
    126                 CtorDtor::generateCtorDtor( translationUnit );
     153
     154                if (!useNewAST) {
     155                        CtorDtor::generateCtorDtor( translationUnit );
     156                }
    127157        }
    128158
     
    196226                        arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
    197227                        // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
     228                        // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
     229                        // still try to detect constant expressions
    198230                        if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    199231
     
    210242
    211243        void HoistArrayDimension::premutate( FunctionDecl * ) {
     244                GuardValue( inFunction );
     245                inFunction = true;
     246        }
     247
     248        // precompute array dimension expression, because constructor generation may duplicate it,
     249        // which would be incorrect if it is a side-effecting computation.
     250        void HoistArrayDimension_NoResolve::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
     251                PassVisitor<HoistArrayDimension_NoResolve> hoister;
     252                mutateAll( translationUnit, hoister );
     253        }
     254
     255        void HoistArrayDimension_NoResolve::premutate( ObjectDecl * objectDecl ) {
     256                GuardValue( storageClasses );
     257                storageClasses = objectDecl->get_storageClasses();
     258        }
     259
     260        DeclarationWithType * HoistArrayDimension_NoResolve::postmutate( ObjectDecl * objectDecl ) {
     261                hoist( objectDecl->get_type() );
     262                return objectDecl;
     263        }
     264
     265        void HoistArrayDimension_NoResolve::hoist( Type * type ) {
     266                // if in function, generate const size_t var
     267                static UniqueName dimensionName( "_array_dim" );
     268
     269                // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension.
     270                if ( ! inFunction ) return;
     271                if ( storageClasses.is_static ) return;
     272
     273                if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
     274                        if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
     275                        // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
     276                        // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
     277                        // still try to detect constant expressions
     278                        if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
     279
     280                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     281                        arrayDimension->get_type()->set_const( true );
     282
     283                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
     284                        declsToAddBefore.push_back( arrayDimension );
     285
     286                        hoist( arrayType->get_base() );
     287                        return;
     288                }
     289        }
     290
     291        void HoistArrayDimension_NoResolve::premutate( FunctionDecl * ) {
    212292                GuardValue( inFunction );
    213293                inFunction = true;
     
    245325        }
    246326
     327        // why is this not just on FunctionDecl?
    247328        void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    248329                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     
    275356        void ManagedTypes::endScope() { managedTypes.endScope(); }
    276357
     358        bool ManagedTypes_new::isManaged( const ast::Type * type ) const {
     359                // references are never constructed
     360                if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false;
     361                if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) {
     362                        // tuple is also managed if any of its components are managed
     363                        for (auto & component : tupleType->types) {
     364                                if (isManaged(component)) return true;
     365                        }
     366                }
     367                // need to clear and reset qualifiers when determining if a type is managed
     368                // ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
     369                auto tmp = shallowCopy(type);
     370                tmp->qualifiers = {};
     371                // delete tmp at return
     372                ast::ptr<ast::Type> guard = tmp;
     373                // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
     374                return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp );
     375        }
     376
     377        bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const {
     378                const ast::Type * type = objDecl->type;
     379                while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
     380                        // must always construct VLAs with an initializer, since this is an error in C
     381                        if ( at->isVarLen && objDecl->init ) return true;
     382                        type = at->base;
     383                }
     384                return isManaged( type );
     385        }
     386
     387        void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) {
     388                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     389                if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) {
     390                        auto & params = GenPoly::getFunctionType( dwt->get_type())->params;
     391                        assert( ! params.empty() );
     392                        // Type * type = InitTweak::getPointerBase( params.front() );
     393                        // assert( type );
     394                        managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
     395                }
     396        }
     397
     398        void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) {
     399                // don't construct members, but need to take note if there is a managed member,
     400                // because that means that this type is also managed
     401                for ( auto & member : aggregateDecl->members ) {
     402                        if ( auto field = member.as<ast::ObjectDecl>() ) {
     403                                if ( isManaged( field ) ) {
     404                                        // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
     405                                        // polymorphic constructors make generic types managed types
     406                                        ast::StructInstType inst( aggregateDecl );
     407                                        managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
     408                                        break;
     409                                }
     410                        }
     411                }
     412        }
     413
     414        void ManagedTypes_new::beginScope() { managedTypes.beginScope(); }
     415        void ManagedTypes_new::endScope() { managedTypes.endScope(); }
     416
    277417        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
    278418                // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     
    283423                assert( stmts.size() <= 1 );
    284424                return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr;
     425
     426        }
     427
     428        ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
     429                assertf(objDecl, "genCtorDtor passed null objDecl");
     430                InitExpander_new srcParam(arg);
     431                return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl);
    285432        }
    286433
     
    363510        // constructable object
    364511        InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
     512        ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl);
    365513       
    366514        ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall(
    367                 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );
     515                srcParam, dstParam, loc, "?{}", objDecl );
    368516        ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall(
    369                 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,
     517                nullParam, dstParam, loc, "^?{}", objDecl,
    370518                SymTab::LoopBackward );
    371519       
  • src/InitTweak/GenInit.h

    rbdfc032 reef8dfb  
    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
     
    5152                GenPoly::ScopedSet< std::string > managedTypes;
    5253        };
     54
     55        class ManagedTypes_new {
     56        public:
     57                bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed
     58                bool isManaged( const ast::Type * type ) const; // determine if type is managed
     59
     60                void handleDWT( const ast::DeclWithType * dwt ); // add type to managed if ctor/dtor
     61                void handleStruct( const ast::StructDecl * aggregateDecl ); // add type to managed if child is managed
     62
     63                void beginScope();
     64                void endScope();
     65        private:
     66                GenPoly::ScopedSet< std::string > managedTypes;
     67        };
    5368} // namespace
    5469
  • src/InitTweak/InitTweak.cc

    rbdfc032 reef8dfb  
    8787                };
    8888
     89                struct HasDesignations_new : public ast::WithShortCircuiting {
     90                        bool result = false;
     91
     92                        void previsit( const ast::Node * ) {
     93                                // short circuit if we already know there are designations
     94                                if ( result ) visit_children = false;
     95                        }
     96
     97                        void previsit( const ast::Designation * des ) {
     98                                // short circuit if we already know there are designations
     99                                if ( result ) visit_children = false;
     100                                else if ( ! des->designators.empty() ) {
     101                                        result = true;
     102                                        visit_children = false;
     103                                }
     104                        }
     105                };
     106
     107                struct InitDepthChecker_new : public ast::WithGuards {
     108                        bool result = true;
     109                        const ast::Type * type;
     110                        int curDepth = 0, maxDepth = 0;
     111                        InitDepthChecker_new( const ast::Type * type ) : type( type ) {
     112                                const ast::Type * t = type;
     113                                while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) {
     114                                        maxDepth++;
     115                                        t = at->base;
     116                                }
     117                                maxDepth++;
     118                        }
     119                        void previsit( ListInit * ) {
     120                                curDepth++;
     121                                GuardAction( [this]() { curDepth--; } );
     122                                if ( curDepth > maxDepth ) result = false;
     123                        }
     124                };
     125
    89126                struct InitFlattener_old : public WithShortCircuiting {
    90127                        void previsit( SingleInit * singleInit ) {
     
    124161        }
    125162
     163        bool isDesignated( const ast::Init * init ) {
     164                ast::Pass<HasDesignations_new> finder;
     165                maybe_accept( init, finder );
     166                return finder.core.result;
     167        }
     168
     169        bool checkInitDepth( const ast::ObjectDecl * objDecl ) {
     170                ast::Pass<InitDepthChecker_new> checker( objDecl->type );
     171                maybe_accept( objDecl->init.get(), checker );
     172                return checker.core.result;
     173        }
     174
    126175std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
    127176        ast::Pass< InitFlattener_new > flattener;
    128177        maybe_accept( init, flattener );
    129         return std::move( flattener.pass.argList );
     178        return std::move( flattener.core.argList );
    130179}
    131180
     
    358407                        if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) {
    359408                                for ( const ast::Init * init : *listInit ) {
    360                                         buildCallExpr( callExpr, index, dimension, init, out );
     409                                        buildCallExpr( shallowCopy(callExpr), index, dimension, init, out );
    361410                                }
    362411                        } else {
    363                                 buildCallExpr( callExpr, index, dimension, init, out );
     412                                buildCallExpr( shallowCopy(callExpr), index, dimension, init, out );
    364413                        }
    365414                } else {
     
    498547        }
    499548
     549        const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) {
     550                assertf( func, "getParamThis: nullptr ftype" );
     551                auto & params = func->params;
     552                assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str());
     553                return params.front().strict_as<ast::ObjectDecl>();
     554        }
     555
    500556        bool tryConstruct( DeclarationWithType * dwt ) {
    501557                ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
     
    511567        }
    512568
     569        bool tryConstruct( const ast::DeclWithType * dwt ) {
     570                auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt );
     571                if ( ! objDecl ) return false;
     572                return (objDecl->init == nullptr ||
     573                                ( objDecl->init != nullptr && objDecl->init->maybeConstructed ))
     574                        && ! objDecl->storage.is_extern
     575                        && isConstructable( objDecl->type );
     576        }
     577
     578        bool isConstructable( const ast::Type * type ) {
     579                return ! dynamic_cast< const ast::VarArgsType * >( type ) && ! dynamic_cast< const ast::ReferenceType * >( type )
     580                && ! dynamic_cast< const ast::FunctionType * >( type ) && ! Tuples::isTtype( type );
     581        }
     582
    513583        struct CallFinder_old {
    514584                CallFinder_old( const std::list< std::string > & names ) : names( names ) {}
     
    536606
    537607        struct CallFinder_new final {
    538                 std::vector< ast::ptr< ast::Expr > > matches;
     608                std::vector< const ast::Expr * > matches;
    539609                const std::vector< std::string > names;
    540610
     
    558628        }
    559629
    560         std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt ) {
     630        std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) {
    561631                ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
    562632                maybe_accept( stmt, finder );
    563                 return std::move( finder.pass.matches );
     633                return std::move( finder.core.matches );
    564634        }
    565635
     
    696766                template <typename Predicate>
    697767                bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
    698                         std::vector< ast::ptr< ast::Expr > > callExprs = collectCtorDtorCalls( stmt );
     768                        std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt );
    699769                        return std::all_of( callExprs.begin(), callExprs.end(), pred );
    700770                }
     
    9391009        }
    9401010
     1011        // looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards
     1012        // following passes may accidentally resolve this expression if returned as untyped...
     1013        ast::Expr * createBitwiseAssignment (const ast::Expr * dst, const ast::Expr * src) {
     1014                static ast::ptr<ast::FunctionDecl> assign = nullptr;
     1015                if (!assign) {
     1016                        auto td = new ast::TypeDecl({}, "T", {}, nullptr, ast::TypeDecl::Dtype, true);
     1017                        assign = new ast::FunctionDecl({}, "?=?", {},
     1018                        { new ast::ObjectDecl({}, "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))),
     1019                          new ast::ObjectDecl({}, "_src", new ast::TypeInstType("T", td))},
     1020                        { new ast::ObjectDecl({}, "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic);
     1021                }
     1022                if (dst->result.as<ast::ReferenceType>()) {
     1023                        for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
     1024                                dst = new ast::AddressExpr(dst);
     1025                        }
     1026                }
     1027                else {
     1028                        dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {}));
     1029                }
     1030                if (src->result.as<ast::ReferenceType>()) {
     1031                        for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
     1032                                src = new ast::AddressExpr(src);
     1033                        }
     1034                }
     1035                return new ast::ApplicationExpr(dst->location, ast::VariableExpr::functionPointer(dst->location, assign), {dst, src});
     1036        }
     1037
    9411038        struct ConstExprChecker : public WithShortCircuiting {
    9421039                // most expressions are not const expr
     
    9791076        };
    9801077
     1078        struct ConstExprChecker_new : public ast::WithShortCircuiting {
     1079                // most expressions are not const expr
     1080                void previsit( const ast::Expr * ) { result = false; visit_children = false; }
     1081
     1082                void previsit( const ast::AddressExpr *addressExpr ) {
     1083                        visit_children = false;
     1084                        const ast::Expr * arg = addressExpr->arg;
     1085
     1086                        // address of a variable or member expression is constexpr
     1087                        if ( ! dynamic_cast< const ast::NameExpr * >( arg )
     1088                        && ! dynamic_cast< const ast::VariableExpr * >( arg )
     1089                        && ! dynamic_cast< const ast::MemberExpr * >( arg )
     1090                        && ! dynamic_cast< const ast::UntypedMemberExpr * >( arg ) ) result = false;
     1091                }
     1092
     1093                // these expressions may be const expr, depending on their children
     1094                void previsit( const ast::SizeofExpr * ) {}
     1095                void previsit( const ast::AlignofExpr * ) {}
     1096                void previsit( const ast::UntypedOffsetofExpr * ) {}
     1097                void previsit( const ast::OffsetofExpr * ) {}
     1098                void previsit( const ast::OffsetPackExpr * ) {}
     1099                void previsit( const ast::CommaExpr * ) {}
     1100                void previsit( const ast::LogicalExpr * ) {}
     1101                void previsit( const ast::ConditionalExpr * ) {}
     1102                void previsit( const ast::CastExpr * ) {}
     1103                void previsit( const ast::ConstantExpr * ) {}
     1104
     1105                void previsit( const ast::VariableExpr * varExpr ) {
     1106                        visit_children = false;
     1107
     1108                        if ( auto inst = varExpr->result.as<ast::EnumInstType>() ) {
     1109                                long long int value;
     1110                                if ( inst->base->valueOf( varExpr->var, value ) ) {
     1111                                        // enumerators are const expr
     1112                                        return;
     1113                                }
     1114                        }
     1115                        result = false;
     1116                }
     1117
     1118                bool result = true;
     1119        };
     1120
    9811121        bool isConstExpr( Expression * expr ) {
    9821122                if ( expr ) {
     
    9981138        }
    9991139
     1140        bool isConstExpr( const ast::Expr * expr ) {
     1141                if ( expr ) {
     1142                        ast::Pass<ConstExprChecker_new> checker;
     1143                        expr->accept( checker );
     1144                        return checker.core.result;
     1145                }
     1146                return true;
     1147        }
     1148
     1149        bool isConstExpr( const ast::Init * init ) {
     1150                if ( init ) {
     1151                        ast::Pass<ConstExprChecker_new> checker;
     1152                        init->accept( checker );
     1153                        return checker.core.result;
     1154                } // if
     1155                // for all intents and purposes, no initializer means const expr
     1156                return true;
     1157        }
     1158
    10001159        bool isConstructor( const std::string & str ) { return str == "?{}"; }
    10011160        bool isDestructor( const std::string & str ) { return str == "^?{}"; }
     
    10261185                if ( ftype->params.size() != 2 ) return false;
    10271186
    1028                 const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() );
     1187                const ast::Type * t1 = getPointerBase( ftype->params.front() );
    10291188                if ( ! t1 ) return false;
    1030                 const ast::Type * t2 = ftype->params.back()->get_type();
     1189                const ast::Type * t2 = ftype->params.back();
    10311190
    10321191                return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
     
    10551214                return isCopyFunction( decl, "?{}" );
    10561215        }
     1216
     1217        void addDataSectonAttribute( ObjectDecl * objDecl ) {
     1218                Type *strLitT = new PointerType( Type::Qualifiers( ),
     1219                        new BasicType( Type::Qualifiers( ), BasicType::Char ) );
     1220                std::list< Expression * > attr_params;
     1221                attr_params.push_back(
     1222                        new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
     1223                objDecl->attributes.push_back(new Attribute("section", attr_params));
     1224        }
     1225
     1226        void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
     1227                auto strLitT = new ast::PointerType(new ast::BasicType(ast::BasicType::Char));
     1228                objDecl->attributes.push_back(new ast::Attribute("section", {new ast::ConstantExpr(objDecl->location, strLitT, "\".data#\"", std::nullopt)}));
     1229        }
     1230
    10571231}
  • src/InitTweak/InitTweak.h

    rbdfc032 reef8dfb  
    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
    5560        bool isDesignated( Initializer * init );
     61        bool isDesignated( const ast::Init * init );
    5662
    5763        /// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
    5864        /// type, where the depth of its type is the number of nested ArrayTypes + 1
    5965        bool checkInitDepth( ObjectDecl * objDecl );
     66        bool checkInitDepth( const ast::ObjectDecl * objDecl );
    6067
    6168        /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
     
    7986        /// get all Ctor/Dtor call expressions from a Statement
    8087        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    81         std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt );
     88        std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt );
    8289
    8390        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
     
    102109        bool isConstExpr( Expression * expr );
    103110        bool isConstExpr( Initializer * init );
     111
     112        bool isConstExpr( const ast::Expr * expr );
     113        bool isConstExpr( const ast::Init * init );
     114
     115        /// Modifies objDecl to have:
     116        ///    __attribute__((section (".data#")))
     117        /// which makes gcc put the declared variable in the data section,
     118        /// which is helpful for global constants on newer gcc versions,
     119        /// so that CFA's generated initialization won't segfault when writing it via a const cast.
     120        /// The trailing # is an injected assembly comment, to suppress the "a" in
     121        ///    .section .data,"a"
     122        ///    .section .data#,"a"
     123        /// to avoid assembler warning "ignoring changed section attributes for .data"
     124        void addDataSectonAttribute( ObjectDecl * objDecl );
     125
     126        void addDataSectionAttribute( ast::ObjectDecl * objDecl );
    104127
    105128        class InitExpander_old {
  • src/InitTweak/module.mk

    rbdfc032 reef8dfb  
    1515###############################################################################
    1616
    17 SRC += InitTweak/GenInit.cc \
     17SRC += \
     18        InitTweak/FixGlobalInit.cc \
     19        InitTweak/FixGlobalInit.h \
    1820        InitTweak/FixInit.cc \
    19         InitTweak/FixGlobalInit.cc \
    20         InitTweak/InitTweak.cc
     21        InitTweak/FixInit.h \
     22        InitTweak/GenInit.cc \
     23        InitTweak/GenInit.h \
     24        InitTweak/InitTweak.cc \
     25        InitTweak/InitTweak.h \
     26        InitTweak/FixInitNew.cpp
    2127
    22 SRCDEMANGLE += InitTweak/GenInit.cc \
    23         InitTweak/InitTweak.cc
     28SRCDEMANGLE += \
     29        InitTweak/GenInit.cc \
     30        InitTweak/GenInit.h \
     31        InitTweak/InitTweak.cc \
     32        InitTweak/InitTweak.h
    2433
Note: See TracChangeset for help on using the changeset viewer.