Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.cc

    r1486116 r906e24d  
    2424#include "MakeLibCfa.h"
    2525#include "Autogen.h"
    26 #include "GenPoly/ScopedSet.h"
    27 #include "SymTab/Mangler.h"
    28 #include "GenPoly/DeclMutator.h"
    2926
    3027namespace SymTab {
     
    3229
    3330        class AutogenerateRoutines : public Visitor {
    34           public:
     31                public:
    3532                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
    36 
    37                 typedef Visitor Parent;
    38                 using Parent::visit;
    3933
    4034                virtual void visit( EnumDecl *enumDecl );
     
    5145                virtual void visit( SwitchStmt *switchStmt );
    5246
    53           private:
     47                AutogenerateRoutines() : functionNesting( 0 ) {}
     48                private:
    5449                template< typename StmtClass > void visitStatement( StmtClass *stmt );
    5550
    5651                std::list< Declaration * > declsToAdd;
    5752                std::set< std::string > structsDone;
    58                 unsigned int functionNesting = 0;     // current level of nested functions
     53                unsigned int functionNesting;     // current level of nested functions
    5954        };
    6055
    61         /// generates routines for tuple types.
    62         /// Doesn't really need to be a mutator, but it's easier to reuse DeclMutator than it is to use AddVisit
    63         /// or anything we currently have that supports adding new declarations for visitors
    64         class AutogenTupleRoutines : public GenPoly::DeclMutator {
    65           public:
    66                 typedef GenPoly::DeclMutator Parent;
    67                 using Parent::mutate;
    68 
    69                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
    70 
    71                 virtual Type * mutate( TupleType *tupleType );
    72 
    73                 virtual CompoundStmt * mutate( CompoundStmt *compoundStmt );
    74 
    75           private:
    76                 unsigned int functionNesting = 0;     // current level of nested functions
    77                 GenPoly::ScopedSet< std::string > seenTuples;
    78         };
    79 
    8056        void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
    81                 AutogenerateRoutines generator;
    82                 acceptAndAdd( translationUnit, generator, false );
    83 
    84                 // needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc.
    85                 // AutogenTupleRoutines tupleGenerator;
    86                 // tupleGenerator.mutateDeclarationList( translationUnit );
     57                AutogenerateRoutines visitor;
     58                acceptAndAdd( translationUnit, visitor, false );
    8759        }
    8860
     
    9163        }
    9264
    93         /// inserts a forward declaration for functionDecl into declsToAdd
    94         void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
    95                 FunctionDecl * decl = functionDecl->clone();
    96                 delete decl->get_statements();
    97                 decl->set_statements( NULL );
    98                 declsToAdd.push_back( decl );
    99                 decl->fixUniqueId();
    100         }
    101 
    102         /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    103         FunctionType * genDefaultType( Type * paramType ) {
    104                 FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    105                 ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr );
    106                 ftype->get_parameters().push_back( dstParam );
    107 
    108                 return ftype;
    109         }
    110 
    111         /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
    112         FunctionType * genCopyType( Type * paramType ) {
    113                 FunctionType *ftype = genDefaultType( paramType );
    114                 ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    115                 ftype->get_parameters().push_back( srcParam );
    116                 return ftype;
    117         }
    118 
    119         /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
    120         FunctionType * genAssignType( Type * paramType ) {
    121                 FunctionType *ftype = genCopyType( paramType );
    122                 ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    123                 ftype->get_returnVals().push_back( returnVal );
    124                 return ftype;
    125         }
    126 
    127         /// true if the aggregate's layout is dynamic
    128         template< typename AggrDecl >
    129         bool hasDynamicLayout( AggrDecl * aggregateDecl ) {
    130                 for ( TypeDecl * param : aggregateDecl->get_parameters() ) {
    131                         if ( param->get_kind() == TypeDecl::Any ) return true;
    132                 }
    133                 return false;
    134         }
    135 
    136         /// generate a function decl from a name and type. Nesting depth determines whether
    137         /// the declaration is static or not; optional paramter determines if declaration is intrinsic
    138         FunctionDecl * genFunc( const std::string & fname, FunctionType * ftype, unsigned int functionNesting, bool isIntrinsic = false  ) {
    139                 // Routines at global scope marked "static" to prevent multiple definitions in separate translation units
     65        template< typename OutputIterator >
     66        void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, OutputIterator out ) {
     67                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
     68                copy->get_args().push_back( new VariableExpr( dstParam ) );
     69                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
     70                copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
     71
     72                *out++ = new ExprStmt( noLabels, copy );
     73        }
     74
     75        //E ?=?(E volatile*, int),
     76        //  ?=?(E _Atomic volatile*, int);
     77        void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
     78                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     79
     80                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType ), 0 );
     81                assignType->get_parameters().push_back( dstParam );
     82
     83                // void ?{}(E *); void ^?{}(E *);
     84                FunctionType * ctorType = assignType->clone();
     85                FunctionType * dtorType = assignType->clone();
     86
     87                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
     88                assignType->get_parameters().push_back( srcParam );
     89                // void ?{}(E *, E);
     90                FunctionType *copyCtorType = assignType->clone();
     91
     92                // T ?=?(E *, E);
     93                ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
     94                assignType->get_returnVals().push_back( returnVal );
     95
     96                // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
     97                // right now these cases work, but that might change.
     98
     99                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    140100                // because each unit generates copies of the default routines for each aggregate.
    141                 DeclarationNode::StorageClass sc = functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static;
    142                 LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen;
    143                 FunctionDecl * decl = new FunctionDecl( fname, sc, spec, ftype, new CompoundStmt( noLabels ), true, false );
    144                 decl->fixUniqueId();
    145                 return decl;
    146         }
    147 
    148         /// generates a single enumeration assignment expression
    149         ApplicationExpr * genEnumAssign( FunctionType * ftype, FunctionDecl * assignDecl ) {
     101                // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
     102                // Really they're something of a cross between instrinsic and autogen, so should
     103                // probably make a new linkage type
     104                FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, new CompoundStmt( noLabels ), true, false );
     105                FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, ctorType, new CompoundStmt( noLabels ), true, false );
     106                FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, copyCtorType, new CompoundStmt( noLabels ), true, false );
     107                FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, dtorType, new CompoundStmt( noLabels ), true, false );
     108                assignDecl->fixUniqueId();
     109                ctorDecl->fixUniqueId();
     110                copyCtorDecl->fixUniqueId();
     111                dtorDecl->fixUniqueId();
     112
    150113                // enum copy construct and assignment is just C-style assignment.
    151114                // this looks like a bad recursive call, but code gen will turn it into
    152115                // a C-style assignment.
    153116                // This happens before function pointer type conversion, so need to do it manually here
    154                 // NOTE: ftype is not necessarily the functionType belonging to assignDecl - ftype is the
    155                 // type of the function that this expression is being generated for (so that the correct
    156                 // parameters) are using in the variable exprs
    157                 assert( ftype->get_parameters().size() == 2 );
    158                 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    159                 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    160 
    161117                VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
    162118                Type * assignVarExprType = assignVarExpr->get_result();
     
    166122                assignExpr->get_args().push_back( new VariableExpr( dstParam ) );
    167123                assignExpr->get_args().push_back( new VariableExpr( srcParam ) );
    168                 return assignExpr;
    169         }
    170 
    171         // E ?=?(E volatile*, int),
    172         //   ?=?(E _Atomic volatile*, int);
    173         void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
    174 
    175                 // T ?=?(E *, E);
    176                 FunctionType *assignType = genAssignType( refType );
    177 
    178                 // void ?{}(E *); void ^?{}(E *);
    179                 FunctionType * ctorType = genDefaultType( refType->clone() );
    180                 FunctionType * dtorType = genDefaultType( refType->clone() );
    181 
    182                 // void ?{}(E *, E);
    183                 FunctionType *copyCtorType = genCopyType( refType->clone() );
    184 
    185                 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
    186                 // right now these cases work, but that might change.
    187 
    188                 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
    189                 // Really they're something of a cross between instrinsic and autogen, so should
    190                 // probably make a new linkage type
    191                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting, true );
    192                 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting, true );
    193                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting, true );
    194                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting, true );
    195124
    196125                // body is either return stmt or expr stmt
    197                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, genEnumAssign( assignType, assignDecl ) ) );
    198                 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, genEnumAssign( copyCtorType, assignDecl ) ) );
    199 
     126                assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, assignExpr ) );
     127                copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, assignExpr->clone() ) );
     128
     129                declsToAdd.push_back( assignDecl );
    200130                declsToAdd.push_back( ctorDecl );
    201131                declsToAdd.push_back( copyCtorDecl );
    202132                declsToAdd.push_back( dtorDecl );
    203                 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    204         }
    205 
    206         /// generates a single struct member operation (constructor call, destructor call, assignment call)
    207         void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
     133        }
     134
     135        /// Clones a reference type, replacing any parameters it may have with a clone of the provided list
     136        template< typename GenericInstType >
     137        GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
     138                GenericInstType *clone = refType->clone();
     139                clone->get_parameters().clear();
     140                cloneAll( params, clone->get_parameters() );
     141                return clone;
     142        }
     143
     144        /// Creates a new type decl that's the same as src, but renamed and with only the ?=?, ?{} (default and copy), and ^?{} assertions (for complete types only)
     145        TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
     146                // TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
     147
     148                // if ( src->get_kind() == TypeDecl::Any ) {
     149                //      TypeInstType *opParamType = new TypeInstType( Type::Qualifiers(), name, dst );
     150                //      FunctionType *opFunctionType = new FunctionType( Type::Qualifiers(), false );
     151                //      opFunctionType->get_parameters().push_back(
     152                //              new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), opParamType->clone() ), 0 ) );
     153                //      FunctionDecl *ctorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
     154                //      FunctionDecl *dtorAssert = new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
     155
     156                //      opFunctionType->get_parameters().push_back(
     157                //              new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType, 0 ) );
     158                //      FunctionDecl *copyCtorAssert = new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType->clone(), 0, false, false );
     159
     160                //      opFunctionType->get_returnVals().push_back(
     161                //              new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, opParamType->clone(), 0 ) );
     162                //      FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, opFunctionType, 0, false, false );
     163
     164
     165                //      dst->get_assertions().push_back( assignAssert );
     166                //      dst->get_assertions().push_back( ctorAssert );
     167                //      dst->get_assertions().push_back( dtorAssert );
     168                //      dst->get_assertions().push_back( copyCtorAssert );
     169                // }
     170
     171                TypeDecl *dst = new TypeDecl( src->get_name(), src->get_storageClass(), 0, src->get_kind() );
     172                cloneAll(src->get_assertions(), dst->get_assertions());
     173                return dst;
     174        }
     175
     176        void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout, bool forward = true ) {
     177//              if ( isDynamicLayout && src ) {
     178//                      genericSubs.apply( src );
     179//              }
     180
    208181                ObjectDecl * returnVal = NULL;
    209182                if ( ! func->get_functionType()->get_returnVals().empty() ) {
     
    214187
    215188                // assign to destination (and return value if generic)
    216                 UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) );
     189                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
     190                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    217191                Expression *dstselect = new MemberExpr( field, derefExpr );
    218192                genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    219193
    220194                if ( isDynamicLayout && returnVal ) {
    221                         // xxx - there used to be a dereference on returnVal, but this seems to have been wrong?
    222                         Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) );
     195                        UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
     196                        derefRet->get_args().push_back( new VariableExpr( returnVal ) );
     197                        Expression *retselect = new MemberExpr( field, derefRet );
    223198                        genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
    224199                } // if
    225200        }
    226201
    227         /// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
    228202        template<typename Iterator>
    229         void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
     203        void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout, bool forward = true ) {
    230204                for ( ; member != end; ++member ) {
    231205                        if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
     
    263237
    264238                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
    265                                 makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout, forward );
     239                                makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isDynamicLayout, forward );
    266240                        } // if
    267241                } // for
     
    271245        /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
    272246        template<typename Iterator>
    273         void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout ) {
     247        void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout ) {
    274248                FunctionType * ftype = func->get_functionType();
    275249                std::list<DeclarationWithType*> & params = ftype->get_parameters();
     
    297271                                        // matching parameter, initialize field with copy ctor
    298272                                        Expression *srcselect = new VariableExpr(*parameter);
    299                                         makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout );
     273                                        makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isDynamicLayout );
    300274                                        ++parameter;
    301275                                } else {
    302276                                        // no matching parameter, initialize field with default ctor
    303                                         makeStructMemberOp( dstParam, NULL, field, func, isDynamicLayout );
     277                                        makeStructMemberOp( dstParam, NULL, field, func, genericSubs, isDynamicLayout );
    304278                                }
    305279                        }
     
    307281        }
    308282
    309         /// generates struct constructors, destructor, and assignment functions
     283        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
     284                FunctionDecl * decl = functionDecl->clone();
     285                delete decl->get_statements();
     286                decl->set_statements( NULL );
     287                declsToAdd.push_back( decl );
     288                decl->fixUniqueId();
     289        }
     290
    310291        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
     292                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    311293
    312294                // Make function polymorphic in same parameters as generic struct, if applicable
    313                 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    314                 bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
     295                bool isDynamicLayout = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
     296                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
     297                std::list< Expression* > structParams;  // List of matching parameters to put on types
     298                TypeSubstitution genericSubs; // Substitutions to make to member types of struct
     299                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
     300                        if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true;
     301                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
     302                        assignType->get_forall().push_back( typeParam );
     303                        TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
     304                        genericSubs.add( (*param)->get_name(), newParamType );
     305                        structParams.push_back( new TypeExpr( newParamType ) );
     306                }
     307
     308                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
     309                assignType->get_parameters().push_back( dstParam );
     310
     311                // void ?{}(T *); void ^?{}(T *);
     312                FunctionType *ctorType = assignType->clone();
     313                FunctionType *dtorType = assignType->clone();
     314
     315                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
     316                assignType->get_parameters().push_back( srcParam );
     317
     318                // void ?{}(T *, T);
     319                FunctionType *copyCtorType = assignType->clone();
    315320
    316321                // T ?=?(T *, T);
    317                 FunctionType *assignType = genAssignType( refType );
    318                 cloneAll( typeParams, assignType->get_forall() );
    319 
    320                 // void ?{}(T *); void ^?{}(T *);
    321                 FunctionType *ctorType = genDefaultType( refType );
    322                 cloneAll( typeParams, ctorType->get_forall() );
    323                 FunctionType *dtorType = genDefaultType( refType );
    324                 cloneAll( typeParams, dtorType->get_forall() );
    325 
    326                 // void ?{}(T *, T);
    327                 FunctionType *copyCtorType = genCopyType( refType );
    328                 cloneAll( typeParams, copyCtorType->get_forall() );
    329 
    330                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
    331                 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting );
    332                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
    333                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
     322                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
     323                assignType->get_returnVals().push_back( returnVal );
     324
     325                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     326                // because each unit generates copies of the default routines for each aggregate.
     327                FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
     328                FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
     329                FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false );
     330                FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
     331                assignDecl->fixUniqueId();
     332                ctorDecl->fixUniqueId();
     333                copyCtorDecl->fixUniqueId();
     334                dtorDecl->fixUniqueId();
    334335
    335336                if ( functionNesting == 0 ) {
    336337                        // forward declare if top-level struct, so that
    337338                        // type is complete as soon as its body ends
    338                         // Note: this is necessary if we want structs which contain
    339                         // generic (otype) structs as members.
    340339                        addForwardDecl( assignDecl, declsToAdd );
    341340                        addForwardDecl( ctorDecl, declsToAdd );
     
    366365                        }
    367366                        memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
    368                         FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    369                         makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout );
     367                        FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType->clone(), new CompoundStmt( noLabels ), true, false );
     368                        ctor->fixUniqueId();
     369                        makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, genericSubs, isDynamicLayout );
    370370                        memCtors.push_back( ctor );
    371371                }
     
    373373
    374374                // generate appropriate calls to member ctor, assignment
    375                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, isDynamicLayout );
    376                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, isDynamicLayout );
    377                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, isDynamicLayout );
     375                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, genericSubs, isDynamicLayout );
     376                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, genericSubs, isDynamicLayout );
     377                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, genericSubs, isDynamicLayout );
    378378                // needs to do everything in reverse, so pass "forward" as false
    379                 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, isDynamicLayout, false );
    380 
    381                 assert( assignType->get_parameters().size() == 2 );
    382                 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() );
    383                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    384 
     379                makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, genericSubs, isDynamicLayout, false );
     380
     381                if ( ! isDynamicLayout ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     382
     383                declsToAdd.push_back( assignDecl );
    385384                declsToAdd.push_back( ctorDecl );
    386385                declsToAdd.push_back( copyCtorDecl );
    387386                declsToAdd.push_back( dtorDecl );
    388                 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    389387                declsToAdd.splice( declsToAdd.end(), memCtors );
    390388        }
    391389
    392         /// generate a single union assignment expression (using memcpy)
    393         template< typename OutputIterator >
    394         void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
    395                 UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    396                 copy->get_args().push_back( new VariableExpr( dstParam ) );
    397                 copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    398                 copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
    399                 *out++ = new ExprStmt( noLabels, copy );
    400         }
    401 
    402         /// generates the body of a union assignment/copy constructor/field constructor
    403         void makeUnionAssignBody( FunctionDecl * funcDecl, bool isDynamicLayout ) {
    404                 FunctionType * ftype = funcDecl->get_functionType();
    405                 assert( ftype->get_parameters().size() == 2 );
    406                 ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    407                 ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    408                 ObjectDecl * returnVal = nullptr;
    409                 if ( ! ftype->get_returnVals().empty() ) {
    410                         returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );
    411                 }
    412 
    413                 makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );
    414                 if ( returnVal ) {
    415                         if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( funcDecl->get_statements()->get_kids() ) );
    416                         else funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    417                 }
    418         }
    419 
    420         /// generates union constructors, destructors, and assignment operator
    421390        void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
     391                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
     392
    422393                // Make function polymorphic in same parameters as generic union, if applicable
    423                 const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    424                 bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
     394                bool isDynamicLayout = false; // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
     395                std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
     396                std::list< Expression* > unionParams;  // List of matching parameters to put on types
     397                for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
     398                        if ( (*param)->get_kind() == TypeDecl::Any ) isDynamicLayout = true;
     399                        TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
     400                        assignType->get_forall().push_back( typeParam );
     401                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
     402                }
     403
     404                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
     405                assignType->get_parameters().push_back( dstParam );
    425406
    426407                // default ctor/dtor need only first parameter
    427                 // void ?{}(T *); void ^?{}(T *);
    428                 FunctionType *ctorType = genDefaultType( refType );
    429                 FunctionType *dtorType = genDefaultType( refType );
     408                FunctionType * ctorType = assignType->clone();
     409                FunctionType * dtorType = assignType->clone();
     410
     411                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
     412                assignType->get_parameters().push_back( srcParam );
    430413
    431414                // copy ctor needs both parameters
    432                 // void ?{}(T *, T);
    433                 FunctionType *copyCtorType = genCopyType( refType );
     415                FunctionType * copyCtorType = assignType->clone();
    434416
    435417                // assignment needs both and return value
    436                 // T ?=?(T *, T);
    437                 FunctionType *assignType = genAssignType( refType );
    438 
    439                 cloneAll( typeParams, ctorType->get_forall() );
    440                 cloneAll( typeParams, dtorType->get_forall() );
    441                 cloneAll( typeParams, copyCtorType->get_forall() );
    442                 cloneAll( typeParams, assignType->get_forall() );
     418                ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
     419                assignType->get_returnVals().push_back( returnVal );
    443420
    444421                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    445422                // because each unit generates copies of the default routines for each aggregate.
    446                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
    447                 FunctionDecl *ctorDecl = genFunc( "?{}",  ctorType, functionNesting );
    448                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
    449                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
    450 
    451                 makeUnionAssignBody( assignDecl, isDynamicLayout );
     423                FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
     424                FunctionDecl *ctorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
     425                FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, NULL, true, false );
     426                FunctionDecl *dtorDecl = new FunctionDecl( "^?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
     427
     428                assignDecl->fixUniqueId();
     429                ctorDecl->fixUniqueId();
     430                copyCtorDecl->fixUniqueId();
     431                dtorDecl->fixUniqueId();
     432
     433                makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( assignDecl->get_statements()->get_kids() ) );
     434                if ( isDynamicLayout ) makeUnionFieldsAssignment( srcParam, returnVal, back_inserter( assignDecl->get_statements()->get_kids() ) );
     435                else assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    452436
    453437                // body of assignment and copy ctor is the same
    454                 makeUnionAssignBody( copyCtorDecl, isDynamicLayout );
     438                copyCtorDecl->set_statements( assignDecl->get_statements()->clone() );
    455439
    456440                // create a constructor which takes the first member type as a parameter.
     
    465449                                FunctionType * memCtorType = ctorType->clone();
    466450                                memCtorType->get_parameters().push_back( srcParam );
    467                                 FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting );
    468 
    469                                 makeUnionAssignBody( ctor, isDynamicLayout );
     451                                FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType, new CompoundStmt( noLabels ), true, false );
     452                                ctor->fixUniqueId();
     453
     454                                makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( ctor->get_statements()->get_kids() ) );
    470455                                memCtors.push_back( ctor );
    471456                                // only generate a ctor for the first field
     
    474459                }
    475460
     461                declsToAdd.push_back( assignDecl );
    476462                declsToAdd.push_back( ctorDecl );
    477463                declsToAdd.push_back( copyCtorDecl );
    478464                declsToAdd.push_back( dtorDecl );
    479                 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    480465                declsToAdd.splice( declsToAdd.end(), memCtors );
    481466        }
     
    493478                if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
    494479                        StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
    495                         for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {
    496                                 structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
    497                         }
    498480                        structInst.set_baseStruct( structDecl );
    499481                        makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
     
    506488                        UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
    507489                        unionInst.set_baseUnion( unionDecl );
    508                         for ( TypeDecl * typeDecl : unionDecl->get_parameters() ) {
    509                                 unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
    510                         }
    511490                        makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
    512491                } // if
     
    514493
    515494        void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
     495                CompoundStmt *stmts = 0;
    516496                TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
    517497                typeInst->set_baseType( typeDecl );
    518                 ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, typeInst->clone(), nullptr );
    519                 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), typeInst->clone() ), nullptr );
    520 
    521                 std::list< Statement * > stmts;
     498                ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
     499                ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
    522500                if ( typeDecl->get_base() ) {
    523501                        // xxx - generate ctor/dtors for typedecls, e.g.
    524502                        // otype T = int *;
     503                        stmts = new CompoundStmt( std::list< Label >() );
    525504                        UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
    526505                        assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
    527506                        assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
    528                         stmts.push_back( new ReturnStmt( std::list< Label >(), assign ) );
     507                        stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
    529508                } // if
    530509                FunctionType *type = new FunctionType( Type::Qualifiers(), false );
     
    532511                type->get_parameters().push_back( dst );
    533512                type->get_parameters().push_back( src );
    534                 FunctionDecl *func = genFunc( "?=?", type, functionNesting );
    535                 func->get_statements()->get_kids() = stmts;
     513                FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, true, false );
    536514                declsToAdd.push_back( func );
    537515        }
     
    578556                visitStatement( switchStmt );
    579557        }
    580 
    581         void makeTupleFunctionBody( FunctionDecl * function ) {
    582                 FunctionType * ftype = function->get_functionType();
    583                 assertf( ftype->get_parameters().size() == 1 || ftype->get_parameters().size() == 2, "too many parameters in generated tuple function" );
    584 
    585                 UntypedExpr * untyped = new UntypedExpr( new NameExpr( function->get_name() ) );
    586 
    587                 /// xxx - &* is used to make this easier for later passes to handle
    588                 untyped->get_args().push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
    589                 if ( ftype->get_parameters().size() == 2 ) {
    590                         untyped->get_args().push_back( new VariableExpr( ftype->get_parameters().back() ) );
    591                 }
    592                 function->get_statements()->get_kids().push_back( new ExprStmt( noLabels, untyped ) );
    593                 function->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
    594         }
    595 
    596         Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) {
    597                 tupleType = safe_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );
    598                 std::string mangleName = SymTab::Mangler::mangleType( tupleType );
    599                 if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;
    600                 seenTuples.insert( mangleName );
    601 
    602                 // T ?=?(T *, T);
    603                 FunctionType *assignType = genAssignType( tupleType );
    604 
    605                 // void ?{}(T *); void ^?{}(T *);
    606                 FunctionType *ctorType = genDefaultType( tupleType );
    607                 FunctionType *dtorType = genDefaultType( tupleType );
    608 
    609                 // void ?{}(T *, T);
    610                 FunctionType *copyCtorType = genCopyType( tupleType );
    611 
    612                 std::set< TypeDecl* > done;
    613                 std::list< TypeDecl * > typeParams;
    614                 for ( Type * t : *tupleType ) {
    615                         if ( TypeInstType * ty = dynamic_cast< TypeInstType * >( t ) ) {
    616                                 if ( ! done.count( ty->get_baseType() ) ) {
    617                                         TypeDecl * newDecl = new TypeDecl( ty->get_baseType()->get_name(), DeclarationNode::NoStorageClass, nullptr, TypeDecl::Any );
    618                                         TypeInstType * inst = new TypeInstType( Type::Qualifiers(), newDecl->get_name(), newDecl );
    619                                         newDecl->get_assertions().push_back( new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genAssignType( inst ), nullptr, true, false ) );
    620                                         newDecl->get_assertions().push_back( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genDefaultType( inst ), nullptr, true, false ) );
    621                                         newDecl->get_assertions().push_back( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genCopyType( inst ), nullptr, true, false ) );
    622                                         newDecl->get_assertions().push_back( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, genDefaultType( inst ), nullptr, true, false ) );
    623                                         typeParams.push_back( newDecl );
    624                                         done.insert( ty->get_baseType() );
    625                                 }
    626                         }
    627                 }
    628                 cloneAll( typeParams, ctorType->get_forall() );
    629                 cloneAll( typeParams, dtorType->get_forall() );
    630                 cloneAll( typeParams, copyCtorType->get_forall() );
    631                 cloneAll( typeParams, assignType->get_forall() );
    632 
    633                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
    634                 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting );
    635                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
    636                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
    637 
    638                 makeTupleFunctionBody( assignDecl );
    639                 makeTupleFunctionBody( ctorDecl );
    640                 makeTupleFunctionBody( copyCtorDecl );
    641                 makeTupleFunctionBody( dtorDecl );
    642 
    643                 addDeclaration( ctorDecl );
    644                 addDeclaration( copyCtorDecl );
    645                 addDeclaration( dtorDecl );
    646                 addDeclaration( assignDecl ); // assignment should come last since it uses copy constructor in return
    647 
    648                 return tupleType;
    649         }
    650 
    651         DeclarationWithType * AutogenTupleRoutines::mutate( FunctionDecl *functionDecl ) {
    652                 functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
    653                 mutateAll( functionDecl->get_oldDecls(), *this );
    654                 functionNesting += 1;
    655                 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
    656                 functionNesting -= 1;
    657                 return functionDecl;
    658         }
    659 
    660         CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) {
    661                 seenTuples.beginScope();
    662                 compoundStmt = safe_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );
    663                 seenTuples.endScope();
    664                 return compoundStmt;
    665         }
    666558} // SymTab
Note: See TracChangeset for help on using the changeset viewer.