Ignore:
Timestamp:
Jan 7, 2021, 3:27:00 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
Children:
2b4daf2, 64aeca0
Parents:
3c64c668 (diff), eef8dfb (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 park_unpark

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r3c64c668 r58fe85a  
    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       
Note: See TracChangeset for help on using the changeset viewer.