Changes in / [e35f30a:4ee36bf0]


Ignore:
Location:
src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    re35f30a r4ee36bf0  
    5454#include "SynTree/Type.h"              // for Type, Type::StorageClasses
    5555#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
     56#include "SynTree/VarExprReplacer.h"   // for VarExprReplacer
    5657#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    5758
     
    158159                        using Parent::previsit;
    159160
    160                         void previsit( ObjectDecl * objDecl );
    161161                        void previsit( FunctionDecl * funcDecl );
    162162
    163                         void previsit( CompoundStmt * compoundStmt );
    164                         void postvisit( CompoundStmt * compoundStmt );
    165                         void previsit( ReturnStmt * returnStmt );
    166163                        void previsit( BranchStmt * stmt );
    167164                private:
     
    203200                        static void generate( std::list< Declaration * > & translationUnit );
    204201
     202                        void previsit( StructDecl * structDecl );
     203
    205204                        void previsit( FunctionDecl * funcDecl );
    206205                        void postvisit( FunctionDecl * funcDecl );
     
    220219                        bool isCtor = false; // true if current function is a constructor
    221220                        StructDecl * structDecl = nullptr;
     221
     222                        // special built-in functions necessary for this to work
     223                        StructDecl * dtorStruct = nullptr;
     224                        FunctionDecl * dtorStructDestroy = nullptr;
    222225                };
    223226
     
    650653                }
    651654
     655                DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * dtor, std::list< Statement * > & stmtsToAdd ) {
     656                        if ( dynamic_cast< ExprStmt * >( dtor ) ) {
     657                                if ( DeclarationWithType * func = getFunction( getCtorDtorCall( dtor ) ) ) {
     658                                        // cleanup argument must be a function, not an object (including function pointer)
     659                                        if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) {
     660                                                if ( dtorFunc->type->forall.empty() ) {
     661                                                        // simple case where the destructor is a monomorphic function call - can simply
     662                                                        // use that function as the cleanup function.
     663                                                        delete dtor;
     664                                                        return func;
     665                                                }
     666                                        }
     667                                }
     668                        }
     669
     670                        // otherwise the cleanup is more complicated - need to build a single argument cleanup function that
     671                        // wraps the more complicated code.
     672                        static UniqueName dtorNamer( "__cleanup_dtor" );
     673                        FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt( noLabels ) );
     674                        stmtsToAdd.push_back( new DeclStmt( noLabels, dtorFunc ) );
     675
     676                        // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter.
     677                        ObjectDecl * thisParam = getParamThis( dtorFunc->type );
     678                        VarExprReplacer::replace( dtor, { std::make_pair( objDecl, thisParam ) } );
     679                        dtorFunc->statements->push_back( dtor );
     680
     681                        return dtorFunc;
     682                }
     683
    652684                DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) {
    653685                        // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
     
    762794                                                        ctorInit->ctor = nullptr;
    763795                                                }
     796
     797                                                Statement * dtor = ctorInit->dtor;
     798                                                if ( dtor ) {
     799                                                        ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor );
     800                                                        Statement * dtorStmt = implicit->callStmt;
     801                                                        // don't need to call intrinsic dtor, because it does nothing, but
     802                                                        // non-intrinsic dtors must be called
     803                                                        if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) {
     804                                                                // set dtor location to the object's location for error messages
     805                                                                DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
     806                                                                objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) );
     807                                                                // objDecl->attributes.push_back( new Attribute( "cleanup", { new NameExpr( dtorFunc->name ) } ) );
     808                                                                ctorInit->dtor = nullptr;
     809                                                        } // if
     810                                                }
    764811                                        } // if
    765812                                } else if ( Initializer * init = ctorInit->init ) {
     
    804851
    805852
    806                 template<typename Iterator, typename OutputIterator>
    807                 void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {
    808                         for ( Iterator it = begin ; it != end ; ++it ) {
    809                                 // extract destructor statement from the object decl and insert it into the output. Note that this is
    810                                 // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually
    811                                 // calls an intrinsic dtor then the call must (and will) still be generated since the argument may
    812                                 // contain side effects.
    813                                 ObjectDecl * objDecl = *it;
    814                                 ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() );
    815                                 assert( ctorInit && ctorInit->get_dtor() );
    816                                 *out++ = ctorInit->get_dtor()->clone();
    817                         } // for
    818                 }
    819 
    820                 void InsertDtors::previsit( ObjectDecl * objDecl ) {
    821                         // remember non-static destructed objects so that their destructors can be inserted later
    822                         if ( ! objDecl->get_storageClasses().is_static ) {
    823                                 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    824                                         // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    825                                         assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    826                                         Statement * dtor = ctorInit->get_dtor();
    827                                         // don't need to call intrinsic dtor, because it does nothing, but
    828                                         // non-intrinsic dtors must be called
    829                                         if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    830                                                 // set dtor location to the object's location for error messages
    831                                                 ctorInit->dtor->location = objDecl->location;
    832                                                 reverseDeclOrder.front().push_front( objDecl );
    833                                         } // if
    834                                 } // if
    835                         } // if
    836                 }
    837 
    838853                void InsertDtors::previsit( FunctionDecl * funcDecl ) {
    839854                        // each function needs to have its own set of labels
     
    848863                }
    849864
    850                 void InsertDtors::previsit( CompoundStmt * compoundStmt ) {
    851                         // visit statements - this will also populate reverseDeclOrder list.  don't want to dump all destructors
    852                         // when block is left, just the destructors associated with variables defined in this block, so push a new
    853                         // list to the top of the stack so that we can differentiate scopes
    854                         reverseDeclOrder.push_front( OrderedDecls() );
    855                         Parent::previsit( compoundStmt );
    856                 }
    857 
    858                 void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {
    859                         // add destructors for the current scope that we're exiting, unless the last statement is a return, which
    860                         // causes unreachable code warnings
    861                         std::list< Statement * > & statements = compoundStmt->get_kids();
    862                         if ( ! statements.empty() && ! dynamic_cast< ReturnStmt * >( statements.back() ) ) {
    863                                 insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( statements ) );
    864                         }
    865                         reverseDeclOrder.pop_front();
    866                 }
    867 
    868                 void InsertDtors::previsit( ReturnStmt * ) {
    869                         // return exits all scopes, so dump destructors for all scopes
    870                         for ( OrderedDecls & od : reverseDeclOrder ) {
    871                                 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );
    872                         } // for
    873                 }
    874 
    875865                // Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
    876866                // BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
     
    900890                        if ( ! diff.empty() ) {
    901891                                throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt );
    902                         } // if
    903                         // S_G-S_L results in set of objects that must be destructed
    904                         diff.clear();
    905                         std::set_difference( curVars.begin(), curVars.end(), lvars.begin(), lvars.end(), std::inserter( diff, diff.end() ) );
    906                         DTOR_PRINT(
    907                                 std::cerr << "S_G-S_L = " << printSet( diff ) << std::endl;
    908                         )
    909                         if ( ! diff.empty() ) {
    910                                 // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages.
    911                                 std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() );
    912 
    913                                 // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor
    914                                 OrderedDecls ordered;
    915                                 for ( OrderedDecls & rdo : reverseDeclOrder ) {
    916                                         // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.
    917                                         copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );
    918                                 } // for
    919                                 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );
    920892                        } // if
    921893                }
     
    956928                }
    957929
     930                void GenStructMemberCalls::previsit( StructDecl * structDecl ) {
     931                        if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
     932                                dtorStruct = structDecl;
     933                        }
     934                }
     935
    958936                void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
    959937                        GuardValue( function );
     
    968946                        unhandled.clear();
    969947                        usedUninit.clear();
     948
     949                        if ( ! dtorStructDestroy && funcDecl->name == "__destroy_Destructor" ) {
     950                                dtorStructDestroy = funcDecl;
     951                                return;
     952                        }
    970953
    971954                        function = funcDecl;
     
    979962                                if ( structType ) {
    980963                                        structDecl = structType->get_baseStruct();
     964                                        if ( structDecl == dtorStruct ) return;
    981965                                        for ( Declaration * member : structDecl->get_members() ) {
    982966                                                if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     
    10501034                                                        callStmt->acceptMutator( resolver );
    10511035                                                        if ( isCtor ) {
    1052                                                                 function->get_statements()->push_front( callStmt );
     1036                                                                function->statements->push_front( callStmt );
    10531037                                                        } else {
    10541038                                                                // destructor statements should be added at the end
    1055                                                                 function->get_statements()->push_back( callStmt );
     1039                                                                // function->get_statements()->push_back( callStmt );
     1040
     1041                                                                // Destructor _dtor0 = { &b.a1, _destroy_A };
     1042                                                                std::list< Statement * > stmtsToAdd;
     1043
     1044                                                                static UniqueName memberDtorNamer = { "__memberDtor" };
     1045                                                                assertf( dtorStruct, "builtin __Destructor not found." );
     1046                                                                assertf( dtorStructDestroy, "builtin __destroy_Destructor not found." );
     1047
     1048                                                                Expression * thisExpr = new AddressExpr( new VariableExpr( thisParam ) );
     1049                                                                Expression * dtorExpr = new VariableExpr( getDtorFunc( thisParam, callStmt, stmtsToAdd ) );
     1050
     1051                                                                ObjectDecl * destructor = ObjectDecl::newObject( memberDtorNamer.newName(), new StructInstType( Type::Qualifiers(), dtorStruct ), new ListInit( { new SingleInit( thisExpr ), new SingleInit( dtorExpr ) } ) );
     1052                                                                function->statements->push_front( new DeclStmt( noLabels, destructor ) );
     1053                                                                destructor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorStructDestroy ) } ) );
     1054
     1055                                                                function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd );
    10561056                                                        }
    10571057                                                } catch ( SemanticError & error ) {
  • src/SymTab/Autogen.cc

    re35f30a r4ee36bf0  
    4646        /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
    4747        struct FuncData {
    48                 typedef FunctionType * (*TypeGen)( Type * );
     48                typedef FunctionType * (*TypeGen)( Type *, bool );
    4949                FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
    5050                std::string fname;
     
    236236
    237237        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    238         FunctionType * genDefaultType( Type * paramType ) {
    239                 const auto & typeParams = getGenericParams( paramType );
     238        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
    240239                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    241                 cloneAll( typeParams, ftype->forall );
     240                if ( maybePolymorphic ) {
     241                        // only copy in
     242                        const auto & typeParams = getGenericParams( paramType );
     243                        cloneAll( typeParams, ftype->forall );
     244                }
    242245                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    243246                ftype->parameters.push_back( dstParam );
     
    246249
    247250        /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
    248         FunctionType * genCopyType( Type * paramType ) {
    249                 FunctionType *ftype = genDefaultType( paramType );
     251        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
     252                FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
    250253                ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    251254                ftype->parameters.push_back( srcParam );
     
    254257
    255258        /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
    256         FunctionType * genAssignType( Type * paramType ) {
    257                 FunctionType *ftype = genCopyType( paramType );
     259        FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
     260                FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
    258261                ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    259262                ftype->returnVals.push_back( returnVal );
     
    313316                for ( const FuncData & d : data ) {
    314317                        // generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
    315                         FunctionType * ftype = d.genType( type );
     318                        FunctionType * ftype = d.genType( type, true );
    316319
    317320                        // destructor for concurrent type must be mutex
  • src/SymTab/Autogen.h

    re35f30a r4ee36bf0  
    4545        extern FunctionDecl * dereferenceOperator;
    4646
    47         // generate the type of an assignment function for paramType
    48         FunctionType * genAssignType( Type * paramType );
    49 
    50         // generate the type of a default constructor or destructor for paramType
    51         FunctionType * genDefaultType( Type * paramType );
    52 
    53         // generate the type of a copy constructor for paramType
    54         FunctionType * genCopyType( Type * paramType );
     47        /// generate the type of an assignment function for paramType.
     48        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     49        FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
     50
     51        /// generate the type of a default constructor or destructor for paramType.
     52        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     53        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
     54
     55        /// generate the type of a copy constructor for paramType.
     56        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     57        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    5558
    5659        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
  • src/SynTree/Mutator.h

    re35f30a r4ee36bf0  
    119119
    120120        virtual TypeSubstitution * mutate( TypeSubstitution * sub );
     121
    121122  private:
    122123        virtual Declaration * handleAggregateDecl(AggregateDecl * aggregateDecl );
  • src/prelude/builtins.c

    re35f30a r4ee36bf0  
    9191static inline unsigned int ?\=?( unsigned int & x, unsigned long int y ) { x = x \ y; return x; }
    9292
     93// type that wraps a pointer and a destructor-like function - used in generating implicit destructor calls for struct members in user-defined functions
     94forall(dtype T)
     95struct __Destructor {
     96  T * object;
     97  void (*dtor)(T *);
     98};
     99
     100// defined destructor in the case that non-generated code wants to use __Destructor
     101forall(dtype T)
     102static inline void ^?{}(__Destructor(T) & x) {
     103  x.dtor(x.object);
     104}
     105
     106// easy interface into __Destructor's destructor for easy codegen purposes
     107extern "C" {
     108  forall(dtype T)
     109  static inline void __destroy_Destructor(__Destructor(T) * dtor) {
     110    ^(*dtor){};
     111  }
     112}
     113
    93114// Local Variables: //
    94115// mode: c //
  • src/tests/.expect/memberCtors-ERR1.txt

    re35f30a r4ee36bf0  
    1 memberCtors.c:71:1 error: in void ?{}(B &b), field a2 used before being constructed
     1memberCtors.c:78:1 error: in void ?{}(B &b), field a2 used before being constructed
  • src/tests/.expect/memberCtors.txt

    re35f30a r4ee36bf0  
    9898end copy construct A
    9999End of main
     100begin destruct B
    100101constructing int
    101102constructing int
     
    146147destructing int: 0
    147148destructing int: 1000
    148 destructing int: 0
    149 destructing int: 0
    150 destructing int: 999
    151 destructing int: 0
    152 destructing int: 0
    153 destructing int: 0
    154 destructing int: 0
    155 destructing int: 0
    156 destructing int: 999
     149end destruct B
     150destructing int: 0
     151destructing int: 0
     152destructing int: 999
     153destructing int: 0
     154destructing int: 0
     155destructing int: 0
     156destructing int: 0
     157destructing int: 0
     158destructing int: 999
     159begin destruct B
    157160constructing int
    158161constructing int
     
    203206destructing int: 0
    204207destructing int: 1000
    205 destructing int: 0
    206 destructing int: 0
    207 destructing int: 999
    208 destructing int: 0
    209 destructing int: 0
    210 destructing int: 0
    211 destructing int: 0
    212 destructing int: 0
    213 destructing int: 999
     208end destruct B
     209destructing int: 0
     210destructing int: 0
     211destructing int: 999
     212destructing int: 0
     213destructing int: 0
     214destructing int: 0
     215destructing int: 0
     216destructing int: 0
     217destructing int: 999
  • src/tests/memberCtors.c

    re35f30a r4ee36bf0  
    2222}
    2323
    24 void ?=?(WrappedInt & this, int x) {
     24/* WrappedInt */ void ?=?(WrappedInt & this, int x) {
    2525  printf("assigning int: %d %d\n", this.x, x);
    2626  this.x = x;
     27  // return this;
    2728}
     29
     30// WrappedInt ?=?(WrappedInt & this, WrappedInt other) {
     31//   printf("assigning int: %d %d\n", this.x, other.x);
     32//   this.x = other.x;
     33//   return this;
     34// }
    2835
    2936struct A {
     
    7986
    8087void ^?{}(B & b) {
     88  printf("begin destruct B\n");
    8189  b.a2 = (A) { 0 };
    8290  ^(b.a1){};
     91  printf("end destruct B\n");
    8392} // a2, a3 never destructed - will be automatically destructed
    8493
    8594int main() {
    8695  printf("Before declaration of b1\n");
    87   B b1;
     96  B b1;  // b1 = { { 1000, 0, 0 }, { 1001, 0, 0 }, { 0, 0, 0 } }
    8897  printf("Before declaration of b2\n");
    8998  B b2 = b1;
  • src/tests/multiDimension.c

    re35f30a r4ee36bf0  
    3232}
    3333
    34 X global[10][10] = {
    35   { 1, { 2 }, { 3 }, { 4 }, 5, 6, 7, 8, 9, 10, 11, 12 },
    36   { 1, 2, 3, 4 },
    37   { { 1234567 } }
    38 };
     34// X global[10][10] = {
     35//   { 1, { 2 }, { 3 }, { 4 }, 5, 6, 7, 8, 9, 10, 11, 12 },
     36//   { 1, 2, 3, 4 },
     37//   { { 1234567 } }
     38// };
    3939
    40 X global2[3][3][3] = {
    41   {
    42     { 1, 2, 3 },
    43     { 4, 5, 6 },
    44     { 7, 8, 9 },
    45     { 10, 11, 12 }
    46   },
    47   {
    48     { 0, 0, 0 }
    49   }
    50 };
     40// X global2[3][3][3] = {
     41//   {
     42//     { 1, 2, 3 },
     43//     { 4, 5, 6 },
     44//     { 7, 8, 9 },
     45//     { 10, 11, 12 }
     46//   },
     47//   {
     48//     { 0, 0, 0 }
     49//   }
     50// };
    5151
    52 int foo() {
    53   static X abc[3][3] = {
    54     { 11, 22, 33, 44 },
    55     { 55, 66 },
    56     { 77 },
    57     { 88, 99, 1010 }
    58   };
    59 }
     52// int foo() {
     53//   static X abc[3][3] = {
     54//     { 11, 22, 33, 44 },
     55//     { 55, 66 },
     56//     { 77 },
     57//     { 88, 99, 1010 }
     58//   };
     59// }
    6060
    6161// ensure constructed const arrays continue to compile
    62 const int global[1] = { -2 };
     62// const int global[1] = { -2 };
    6363
    6464int main() {
    65   X abc[4][4] = {
    66     { 999, 1111 },
    67     { 1, 2, 3, 4, 5 },
    68     {},
    69     { 0 },
    70     { 88 }
    71   };
     65  X a;
     66  X abc[2];
     67  // X abc[4]/*[4]*/ = {
     68  //   /*{*/ 999, 1111 /*}*/,
     69  //   // { 1, 2, 3, 4, 5 },
     70  //   // {},
     71  //   // { 0 },
     72  //   // { 88 }
     73  // };
    7274
    73   foo();
    74   foo();
     75  // foo();
     76  // foo();
    7577}
Note: See TracChangeset for help on using the changeset viewer.