Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r09867ec r07de76b  
    2626#include "AST/Node.hpp"
    2727#include "AST/Stmt.hpp"
    28 #include "CompilationState.h"
    2928#include "CodeGen/OperatorTable.h"
    3029#include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
     
    122121        };
    123122
    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 
    145123        void genInit( std::list< Declaration * > & translationUnit ) {
    146                 if (!useNewAST) {
    147                         HoistArrayDimension::hoistArrayDimension( translationUnit );
    148                 }
    149                 else {
    150                         HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit );
    151                 }
    152124                fixReturnStatements( translationUnit );
    153 
    154                 if (!useNewAST) {
    155                         CtorDtor::generateCtorDtor( translationUnit );
    156                 }
     125                HoistArrayDimension::hoistArrayDimension( translationUnit );
     126                CtorDtor::generateCtorDtor( translationUnit );
    157127        }
    158128
     
    226196                        arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
    227197                        // 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
    230198                        if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    231199
     
    242210
    243211        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 * ) {
    292212                GuardValue( inFunction );
    293213                inFunction = true;
     
    325245        }
    326246
    327         // why is this not just on FunctionDecl?
    328247        void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    329248                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     
    356275        void ManagedTypes::endScope() { managedTypes.endScope(); }
    357276
    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 
    417277        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
    418278                // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     
    423283                assert( stmts.size() <= 1 );
    424284                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);
    432285        }
    433286
     
    510363        // constructable object
    511364        InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
    512         ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl);
    513365       
    514366        ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall(
    515                 srcParam, dstParam, loc, "?{}", objDecl );
     367                srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );
    516368        ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall(
    517                 nullParam, dstParam, loc, "^?{}", objDecl,
     369                nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,
    518370                SymTab::LoopBackward );
    519371       
Note: See TracChangeset for help on using the changeset viewer.