Changes in / [4ee36bf0:e35f30a]


Ignore:
Location:
src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r4ee36bf0 re35f30a  
    5454#include "SynTree/Type.h"              // for Type, Type::StorageClasses
    5555#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    56 #include "SynTree/VarExprReplacer.h"   // for VarExprReplacer
    5756#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    5857
     
    159158                        using Parent::previsit;
    160159
     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 );
    163166                        void previsit( BranchStmt * stmt );
    164167                private:
     
    200203                        static void generate( std::list< Declaration * > & translationUnit );
    201204
    202                         void previsit( StructDecl * structDecl );
    203 
    204205                        void previsit( FunctionDecl * funcDecl );
    205206                        void postvisit( FunctionDecl * funcDecl );
     
    219220                        bool isCtor = false; // true if current function is a constructor
    220221                        StructDecl * structDecl = nullptr;
    221 
    222                         // special built-in functions necessary for this to work
    223                         StructDecl * dtorStruct = nullptr;
    224                         FunctionDecl * dtorStructDestroy = nullptr;
    225222                };
    226223
     
    653650                }
    654651
    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 
    684652                DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) {
    685653                        // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
     
    794762                                                        ctorInit->ctor = nullptr;
    795763                                                }
    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                                                 }
    811764                                        } // if
    812765                                } else if ( Initializer * init = ctorInit->init ) {
     
    851804
    852805
     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
    853838                void InsertDtors::previsit( FunctionDecl * funcDecl ) {
    854839                        // each function needs to have its own set of labels
     
    863848                }
    864849
     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
    865875                // Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
    866876                // BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
     
    890900                        if ( ! diff.empty() ) {
    891901                                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 ) );
    892920                        } // if
    893921                }
     
    928956                }
    929957
    930                 void GenStructMemberCalls::previsit( StructDecl * structDecl ) {
    931                         if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
    932                                 dtorStruct = structDecl;
    933                         }
    934                 }
    935 
    936958                void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
    937959                        GuardValue( function );
     
    946968                        unhandled.clear();
    947969                        usedUninit.clear();
    948 
    949                         if ( ! dtorStructDestroy && funcDecl->name == "__destroy_Destructor" ) {
    950                                 dtorStructDestroy = funcDecl;
    951                                 return;
    952                         }
    953970
    954971                        function = funcDecl;
     
    962979                                if ( structType ) {
    963980                                        structDecl = structType->get_baseStruct();
    964                                         if ( structDecl == dtorStruct ) return;
    965981                                        for ( Declaration * member : structDecl->get_members() ) {
    966982                                                if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     
    10341050                                                        callStmt->acceptMutator( resolver );
    10351051                                                        if ( isCtor ) {
    1036                                                                 function->statements->push_front( callStmt );
     1052                                                                function->get_statements()->push_front( callStmt );
    10371053                                                        } else {
    10381054                                                                // destructor statements should be added at the end
    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 );
     1055                                                                function->get_statements()->push_back( callStmt );
    10561056                                                        }
    10571057                                                } catch ( SemanticError & error ) {
  • src/SymTab/Autogen.cc

    r4ee36bf0 re35f30a  
    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 *, bool );
     48                typedef FunctionType * (*TypeGen)( Type * );
    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, bool maybePolymorphic ) {
     238        FunctionType * genDefaultType( Type * paramType ) {
     239                const auto & typeParams = getGenericParams( paramType );
    239240                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    240                 if ( maybePolymorphic ) {
    241                         // only copy in
    242                         const auto & typeParams = getGenericParams( paramType );
    243                         cloneAll( typeParams, ftype->forall );
    244                 }
     241                cloneAll( typeParams, ftype->forall );
    245242                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    246243                ftype->parameters.push_back( dstParam );
     
    249246
    250247        /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
    251         FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
    252                 FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
     248        FunctionType * genCopyType( Type * paramType ) {
     249                FunctionType *ftype = genDefaultType( paramType );
    253250                ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    254251                ftype->parameters.push_back( srcParam );
     
    257254
    258255        /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
    259         FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
    260                 FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
     256        FunctionType * genAssignType( Type * paramType ) {
     257                FunctionType *ftype = genCopyType( paramType );
    261258                ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    262259                ftype->returnVals.push_back( returnVal );
     
    316313                for ( const FuncData & d : data ) {
    317314                        // generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
    318                         FunctionType * ftype = d.genType( type, true );
     315                        FunctionType * ftype = d.genType( type );
    319316
    320317                        // destructor for concurrent type must be mutex
  • src/SymTab/Autogen.h

    r4ee36bf0 re35f30a  
    4545        extern FunctionDecl * dereferenceOperator;
    4646
    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 );
     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 );
    5855
    5956        /// 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

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

    r4ee36bf0 re35f30a  
    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
    94 forall(dtype T)
    95 struct __Destructor {
    96   T * object;
    97   void (*dtor)(T *);
    98 };
    99 
    100 // defined destructor in the case that non-generated code wants to use __Destructor
    101 forall(dtype T)
    102 static inline void ^?{}(__Destructor(T) & x) {
    103   x.dtor(x.object);
    104 }
    105 
    106 // easy interface into __Destructor's destructor for easy codegen purposes
    107 extern "C" {
    108   forall(dtype T)
    109   static inline void __destroy_Destructor(__Destructor(T) * dtor) {
    110     ^(*dtor){};
    111   }
    112 }
    113 
    11493// Local Variables: //
    11594// mode: c //
  • src/tests/.expect/memberCtors-ERR1.txt

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

    r4ee36bf0 re35f30a  
    9898end copy construct A
    9999End of main
    100 begin destruct B
    101100constructing int
    102101constructing int
     
    147146destructing int: 0
    148147destructing int: 1000
    149 end destruct B
    150 destructing int: 0
    151 destructing int: 0
    152 destructing int: 999
    153 destructing int: 0
    154 destructing int: 0
    155 destructing int: 0
    156 destructing int: 0
    157 destructing int: 0
    158 destructing int: 999
    159 begin destruct B
     148destructing int: 0
     149destructing int: 0
     150destructing int: 999
     151destructing int: 0
     152destructing int: 0
     153destructing int: 0
     154destructing int: 0
     155destructing int: 0
     156destructing int: 999
    160157constructing int
    161158constructing int
     
    206203destructing int: 0
    207204destructing int: 1000
    208 end destruct B
    209 destructing int: 0
    210 destructing int: 0
    211 destructing int: 999
    212 destructing int: 0
    213 destructing int: 0
    214 destructing int: 0
    215 destructing int: 0
    216 destructing int: 0
    217 destructing int: 999
     205destructing int: 0
     206destructing int: 0
     207destructing int: 999
     208destructing int: 0
     209destructing int: 0
     210destructing int: 0
     211destructing int: 0
     212destructing int: 0
     213destructing int: 999
  • src/tests/memberCtors.c

    r4ee36bf0 re35f30a  
    2222}
    2323
    24 /* WrappedInt */ void ?=?(WrappedInt & this, int x) {
     24void ?=?(WrappedInt & this, int x) {
    2525  printf("assigning int: %d %d\n", this.x, x);
    2626  this.x = x;
    27   // return this;
    2827}
    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 // }
    3528
    3629struct A {
     
    8679
    8780void ^?{}(B & b) {
    88   printf("begin destruct B\n");
    8981  b.a2 = (A) { 0 };
    9082  ^(b.a1){};
    91   printf("end destruct B\n");
    9283} // a2, a3 never destructed - will be automatically destructed
    9384
    9485int main() {
    9586  printf("Before declaration of b1\n");
    96   B b1;  // b1 = { { 1000, 0, 0 }, { 1001, 0, 0 }, { 0, 0, 0 } }
     87  B b1;
    9788  printf("Before declaration of b2\n");
    9889  B b2 = b1;
  • src/tests/multiDimension.c

    r4ee36bf0 re35f30a  
    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 // };
     34X 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 // };
     40X 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 // }
     52int 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 };
     62const int global[1] = { -2 };
    6363
    6464int main() {
    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   // };
     65  X abc[4][4] = {
     66    { 999, 1111 },
     67    { 1, 2, 3, 4, 5 },
     68    {},
     69    { 0 },
     70    { 88 }
     71  };
    7472
    75   // foo();
    76   // foo();
     73  foo();
     74  foo();
    7775}
Note: See TracChangeset for help on using the changeset viewer.