Changeset 16ba4a6f for src/InitTweak


Ignore:
Timestamp:
Nov 10, 2020, 12:20:37 AM (5 years ago)
Author:
Fangren Yu <f37yu@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
18f0b70
Parents:
3febb2d
Message:

factor out resolver calls in pre-resolution stage

Location:
src/InitTweak
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r3febb2d r16ba4a6f  
    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...
     
    122123
    123124        void genInit( std::list< Declaration * > & translationUnit ) {
     125                HoistArrayDimension::hoistArrayDimension( translationUnit );
    124126                fixReturnStatements( translationUnit );
    125                 HoistArrayDimension::hoistArrayDimension( translationUnit );
    126                 CtorDtor::generateCtorDtor( translationUnit );
     127
     128                if (!useNewAST) {
     129                        CtorDtor::generateCtorDtor( translationUnit );
     130                }
    127131        }
    128132
     
    192196
    193197                        // need to resolve array dimensions in order to accurately determine if constexpr
    194                         ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
    195                         // array is variable-length when the dimension is not constexpr
    196                         arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
     198                        if (!useNewAST) {
     199                                ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
     200                                // array is variable-length when the dimension is not constexpr
     201                                arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
     202                        }
    197203                        // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
    198                         if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
     204                        // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve     
     205                        // only skip in the most trivial case, which does not require resolve
     206                        if (dynamic_cast<ConstantExpr *>(arrayType->dimension)) return;
     207                        // if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    199208
    200209                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     
    245254        }
    246255
     256        // why is this not just on FunctionDecl?
    247257        void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    248258                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     
    274284        void ManagedTypes::beginScope() { managedTypes.beginScope(); }
    275285        void ManagedTypes::endScope() { managedTypes.endScope(); }
     286
     287        bool ManagedTypes_new::isManaged( const ast::Type * type ) const {
     288                // references are never constructed
     289                if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false;
     290                if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) {
     291                        // tuple is also managed if any of its components are managed
     292                        for (auto & component : tupleType->types) {
     293                                if (isManaged(component)) return true;
     294                        }
     295                }
     296                // need to clear and reset qualifiers when determining if a type is managed
     297                // ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
     298                auto tmp = shallowCopy(type);
     299                tmp->qualifiers = {};
     300                // delete tmp at return
     301                ast::ptr<ast::Type> guard = tmp;
     302                // 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)
     303                return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp );
     304        }
     305
     306        bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const {
     307                const ast::Type * type = objDecl->type;
     308                while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
     309                        // must always construct VLAs with an initializer, since this is an error in C
     310                        if ( at->isVarLen && objDecl->init ) return true;
     311                        type = at->base;
     312                }
     313                return isManaged( type );
     314        }
     315
     316        void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) {
     317                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     318                if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) {
     319                        auto & params = GenPoly::getFunctionType( dwt->get_type())->params;
     320                        assert( ! params.empty() );
     321                        // Type * type = InitTweak::getPointerBase( params.front() );
     322                        // assert( type );
     323                        managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
     324                }
     325        }
     326
     327        void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) {
     328                // don't construct members, but need to take note if there is a managed member,
     329                // because that means that this type is also managed
     330                for ( auto & member : aggregateDecl->members ) {
     331                        if ( auto field = member.as<ast::ObjectDecl>() ) {
     332                                if ( isManaged( field ) ) {
     333                                        // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
     334                                        // polymorphic constructors make generic types managed types
     335                                        ast::StructInstType inst( aggregateDecl );
     336                                        managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
     337                                        break;
     338                                }
     339                        }
     340                }
     341        }
     342
     343        void ManagedTypes_new::beginScope() { managedTypes.beginScope(); }
     344        void ManagedTypes_new::endScope() { managedTypes.endScope(); }
    276345
    277346        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
     
    370439        // constructable object
    371440        InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
     441        ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl);
    372442       
    373443        ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall(
    374                 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );
     444                srcParam, dstParam, loc, "?{}", objDecl );
    375445        ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall(
    376                 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,
     446                nullParam, dstParam, loc, "^?{}", objDecl,
    377447                SymTab::LoopBackward );
    378448       
  • src/InitTweak/GenInit.h

    r3febb2d r16ba4a6f  
    5252                GenPoly::ScopedSet< std::string > managedTypes;
    5353        };
     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        };
    5468} // namespace
    5569
  • src/InitTweak/InitTweak.cc

    r3febb2d r16ba4a6f  
    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 ) {
     
    122159                maybeAccept( objDecl->init, checker );
    123160                return checker.pass.depthOkay;
     161        }
     162
     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;
    124173        }
    125174
     
    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 {
     
    10271076        };
    10281077
     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
    10291121        bool isConstExpr( Expression * expr ) {
    10301122                if ( expr ) {
     
    10461138        }
    10471139
     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
    10481159        bool isConstructor( const std::string & str ) { return str == "?{}"; }
    10491160        bool isDestructor( const std::string & str ) { return str == "^?{}"; }
  • src/InitTweak/InitTweak.h

    r3febb2d r16ba4a6f  
    5959        /// True if the Initializer contains designations
    6060        bool isDesignated( Initializer * init );
     61        bool isDesignated( const ast::Init * init );
    6162
    6263        /// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
    6364        /// type, where the depth of its type is the number of nested ArrayTypes + 1
    6465        bool checkInitDepth( ObjectDecl * objDecl );
     66        bool checkInitDepth( const ast::ObjectDecl * objDecl );
    6567
    6668        /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
     
    107109        bool isConstExpr( Expression * expr );
    108110        bool isConstExpr( Initializer * init );
     111
     112        bool isConstExpr( const ast::Expr * expr );
     113        bool isConstExpr( const ast::Init * init );
    109114
    110115        /// Modifies objDecl to have:
Note: See TracChangeset for help on using the changeset viewer.