Changeset 395fc37


Ignore:
Timestamp:
Mar 16, 2017, 6:14:32 PM (5 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
615a096
Parents:
6f95000 (diff), 1fbab5a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg2:software/cfa/cfa-cc

Files:
12 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    r6f95000 r395fc37  
    4040\newcommand{\CC}{\rm C\kern-.1em\hbox{+\kern-.25em+}\xspace} % CC symbolic name
    4141\newcommand{\CCeleven}{\rm C\kern-.1em\hbox{+\kern-.25em+}11\xspace} % C++11 symbolic name
     42\newcommand{\CCseventeen}{\rm C\kern-.1em\hbox{+\kern-.25em+}17\xspace} % C++17 symbolic name
    4243\newcommand{\Celeven}{C11\xspace}               % C11 symbolic name
    4344\newcommand{\Csharp}{C\raisebox{0.4ex}{\#}\xspace}      % C# symbolic name
  • src/GenPoly/Specialize.cc

    r6f95000 r395fc37  
    7777        }
    7878
     79        /// True if both types have the same structure, but not necessarily the same types.
     80        /// That is, either both types are tuple types with the same size (recursively), or
     81        /// both are not tuple types.
     82        bool matchingTupleStructure( Type * t1, Type * t2 ) {
     83                TupleType * tuple1 = dynamic_cast< TupleType * >( t1 );
     84                TupleType * tuple2 = dynamic_cast< TupleType * >( t2 );
     85                if ( tuple1 && tuple2 ) {
     86                        if ( tuple1->size() != tuple2->size() ) return false;
     87                        for ( auto types : group_iterate( tuple1->get_types(), tuple2->get_types() ) ) {
     88                                if ( ! matchingTupleStructure( std::get<0>( types ), std::get<1>( types ) ) ) return false;
     89                        }
     90                        return true;
     91                } else if ( ! tuple1 && ! tuple2 ) return true;
     92                return false;
     93        }
     94
    7995        bool needsTupleSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
    80                 if ( FunctionType * ftype = getFunctionType( formalType ) ) {
    81                         return ftype->isTtype();
     96                // Needs tuple specialization if the structure of the formal type and actual type do not match.
     97                // This is the case if the formal type has ttype polymorphism, or if the structure  of tuple types
     98                // between the function do not match exactly.
     99                if ( FunctionType * fftype = getFunctionType( formalType ) ) {
     100                        if ( fftype->isTtype() ) return true;
     101                        FunctionType * aftype = getFunctionType( actualType );
     102                        assertf( aftype, "formal type is a function type, but actual type is not." );
     103                        if ( fftype->get_parameters().size() != aftype->get_parameters().size() ) return true;
     104                        for ( auto params : group_iterate( fftype->get_parameters(), aftype->get_parameters() ) ) {
     105                                DeclarationWithType * formal = std::get<0>(params);
     106                                DeclarationWithType * actual = std::get<1>(params);
     107                                if ( ! matchingTupleStructure( formal->get_type(), actual->get_type() ) ) return true;
     108                        }
    82109                }
    83110                return false;
     
    110137        }
    111138
    112         /// restructures arg to match the structure of a single formal parameter. Assumes that atomic types are compatible (as the Resolver should have ensured this)
    113         template< typename OutIterator >
    114         void matchOneFormal( Expression * arg, unsigned & idx, Type * formal, OutIterator out ) {
    115                 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formal ) ) {
     139        /// restructures the arguments to match the structure of the formal parameters of the actual function.
     140        /// [begin, end) are the exploded arguments.
     141        template< typename Iterator, typename OutIterator >
     142        void structureArg( Type * type, Iterator & begin, Iterator end, OutIterator out ) {
     143                if ( TupleType * tuple = dynamic_cast< TupleType * >( type ) ) {
    116144                        std::list< Expression * > exprs;
    117                         for ( Type * t : *tupleType ) {
    118                                 matchOneFormal( arg, idx, t, back_inserter( exprs ) );
     145                        for ( Type * t : *tuple ) {
     146                                structureArg( t, begin, end, back_inserter( exprs ) );
    119147                        }
    120148                        *out++ = new TupleExpr( exprs );
    121149                } else {
    122                         *out++ = new TupleIndexExpr( arg->clone(), idx++ );
    123                 }
    124         }
    125 
    126         /// restructures the ttype argument to match the structure of the formal parameters of the actual function.
    127         /// [begin, end) are the formal parameters.
    128         /// args is the list of arguments currently given to the actual function, the last of which needs to be restructured.
    129         template< typename Iterator, typename OutIterator >
    130         void fixLastArg( Expression * last, Iterator begin, Iterator end, OutIterator out ) {
    131                 if ( Tuples::isTtype( last->get_result() ) ) {
    132                         *out++ = last;
    133                 } else {
    134                         // safe_dynamic_cast for the assertion
    135                         safe_dynamic_cast< TupleType * >( last->get_result() );
    136                         unsigned idx = 0;
    137                         for ( ; begin != end; ++begin ) {
    138                                 DeclarationWithType * formal = *begin;
    139                                 Type * formalType = formal->get_type();
    140                                 matchOneFormal( last, idx, formalType, out );
    141                         }
    142                         delete last;
     150                        assertf( begin != end, "reached the end of the arguments while structuring" );
     151                        *out++ = *begin++;
     152                }
     153        }
     154
     155        /// explode assuming simple cases: either type is pure tuple (but not tuple expr) or type is non-tuple.
     156        template< typename OutputIterator >
     157        void explodeSimple( Expression * expr, OutputIterator out ) {
     158                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( expr->get_result() ) ) {
     159                        // tuple type, recursively index into its components
     160                        for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
     161                                explodeSimple( new TupleIndexExpr( expr->clone(), i ), out );
     162                        }
     163                        delete expr;
     164                } else {
     165                        // non-tuple type - output a clone of the expression
     166                        *out++ = expr;
    143167                }
    144168        }
     
    173197                std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin();
    174198                std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end();
    175                 std::list< DeclarationWithType * >::iterator formalBegin = funType->get_parameters().begin();
    176                 std::list< DeclarationWithType * >::iterator formalEnd = funType->get_parameters().end();
    177 
     199
     200                std::list< Expression * > args;
    178201                for ( DeclarationWithType* param : thunkFunc->get_functionType()->get_parameters() ) {
    179                         // walk the parameters to the actual function alongside the parameters to the thunk to find the location where the ttype parameter begins to satisfy parameters in the actual function.
     202                        // name each thunk parameter and explode it - these are then threaded back into the actual function call.
    180203                        param->set_name( paramNamer.newName() );
    181                         assertf( formalBegin != formalEnd, "Reached end of formal parameters before finding ttype parameter" );
    182                         if ( Tuples::isTtype((*formalBegin)->get_type()) ) {
    183                                 fixLastArg( new VariableExpr( param ), actualBegin, actualEnd, back_inserter( appExpr->get_args() ) );
    184                                 break;
    185                         }
    186                         assertf( actualBegin != actualEnd, "reached end of actual function's arguments before finding ttype parameter" );
    187                         ++actualBegin;
    188                         ++formalBegin;
    189 
    190                         appExpr->get_args().push_back( new VariableExpr( param ) );
    191                 } // for
     204                        explodeSimple( new VariableExpr( param ), back_inserter( args ) );
     205                }
     206
     207                // walk parameters to the actual function alongside the exploded thunk parameters and restructure the arguments to match the actual parameters.
     208                std::list< Expression * >::iterator argBegin = args.begin(), argEnd = args.end();
     209                for ( ; actualBegin != actualEnd; ++actualBegin ) {
     210                        structureArg( (*actualBegin)->get_type(), argBegin, argEnd, back_inserter( appExpr->get_args() ) );
     211                }
     212
    192213                appExpr->set_env( maybeClone( env ) );
    193214                if ( inferParams ) {
  • src/InitTweak/GenInit.cc

    r6f95000 r395fc37  
    218218
    219219        bool CtorDtor::isManaged( Type * type ) const {
     220                // need to clear and reset qualifiers when determining if a type is managed
     221                ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
     222                type->get_qualifiers() = Type::Qualifiers();
    220223                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    221224                        // tuple is also managed if any of its components are managed
  • src/Parser/parser.yy

    r6f95000 r395fc37  
    412412                { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_REALFRACTIONconstant( *$2 ) ) ); }
    413413        | postfix_expression ARROW no_attr_identifier
    414                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
     414                {
     415                        $$ = new ExpressionNode( build_pfieldSel( $1, *$3 == "0" || *$3 == "1" ? build_constantInteger( *$3 ) : build_varref( $3 ) ) );
     416                }
    415417        | postfix_expression ARROW '[' push field_list pop ']' // CFA, tuple field selector
    416418                        { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $5 ) ) ); }
     419        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
     420                { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
    417421        | postfix_expression ICR
    418422                { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); }
  • src/ResolvExpr/Resolver.cc

    r6f95000 r395fc37  
    240240                functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
    241241                Parent::visit( functionDecl );
     242
     243                // default value expressions have an environment which shouldn't be there and trips up later passes.
     244                // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
     245                // see how it's useful.
     246                for ( Declaration * d : functionDecl->get_functionType()->get_parameters() ) {
     247                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     248                                if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->get_init() ) ) {
     249                                        delete init->get_value()->get_env();
     250                                        init->get_value()->set_env( nullptr );
     251                                }
     252                        }
     253                }
    242254        }
    243255
  • src/SymTab/Autogen.cc

    r6f95000 r395fc37  
    151151        bool hasDynamicLayout( AggrDecl * aggregateDecl ) {
    152152                for ( TypeDecl * param : aggregateDecl->get_parameters() ) {
    153                         if ( param->get_kind() == TypeDecl::Any ) return true;
     153                        if ( param->isComplete() ) return true;
    154154                }
    155155                return false;
  • src/SymTab/Indexer.cc

    r6f95000 r395fc37  
    119119                                FunctionDecl * decl;
    120120                                bool isUserDefinedFunc; // properties for this particular decl
    121                                 bool isDefaultFunc;
     121                                bool isDefaultCtor;
     122                                bool isDtor;
    122123                                bool isCopyFunc;
    123124                        };
    124125                        // properties for this type
    125                         bool userDefinedFunc = false; // any user defined function found
    126                         bool userDefinedDefaultFunc = false; // user defined default ctor found
    127                         bool userDefinedCopyFunc = false; // user defined copy ctor found
     126                        bool userDefinedFunc = false; // any user-defined function found
     127                        bool userDefinedCtor = false; // any user-defined constructor found
     128                        bool userDefinedDtor = false; // any user-defined destructor found
     129                        bool userDefinedCopyFunc = false; // user-defined copy ctor found
    128130                        std::list< DeclBall > decls;
    129131
     
    132134                        ValueType & operator+=( FunctionDecl * function ) {
    133135                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->get_linkage() );
    134                                 bool isDefaultFunc = function->get_functionType()->get_parameters().size() == 1;
     136                                bool isDefaultCtor = InitTweak::isDefaultConstructor( function );
     137                                bool isDtor = InitTweak::isDestructor( function );
    135138                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
    136                                 decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultFunc, isCopyFunc } );
     139                                decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
    137140                                userDefinedFunc = userDefinedFunc || isUserDefinedFunc;
    138                                 userDefinedDefaultFunc = userDefinedDefaultFunc || (isUserDefinedFunc && isDefaultFunc);
     141                                userDefinedCtor = userDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) );
     142                                userDefinedDtor = userDefinedDtor || (isUserDefinedFunc && isDtor);
    139143                                userDefinedCopyFunc = userDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
    140144                                return *this;
     
    163167                // a default ctor, then the generated default ctor should never be seen, likewise for copy ctor
    164168                // and dtor. If the user defines any ctor/dtor, then no generated field ctors should be seen.
     169                // If the user defines any ctor then the generated default ctor should not be seen.
    165170                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
    166171                        ValueType & val = pair.second;
    167172                        for ( ValueType::DeclBall ball : val.decls ) {
    168                                 if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefinedDefaultFunc && ball.isDefaultFunc) || (! val.userDefinedCopyFunc && ball.isCopyFunc) ) {
     173                                if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefinedCtor && ball.isDefaultCtor) || (! val.userDefinedCopyFunc && ball.isCopyFunc) || (! val.userDefinedDtor && ball.isDtor) ) {
    169174                                        // decl conforms to the rules described above, so it should be seen by the requester
    170175                                        out.push_back( ball.decl );
  • src/SymTab/Validate.cc

    r6f95000 r395fc37  
    224224                HoistStruct::hoistStruct( translationUnit );
    225225                ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
     226                acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
    226227                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
    227228                acceptAll( translationUnit, epc );
    228                 acceptAll( translationUnit, lrt );
    229229                ReturnChecker::checkFunctionReturns( translationUnit );
    230230                compoundliteral.mutateDeclarationList( translationUnit );
     
    840840                assertf( retVals.size() == 0 || retVals.size() == 1, "Function %s has too many return values: %d", functionDecl->get_name().c_str(), retVals.size() );
    841841                if ( retVals.size() == 1 ) {
    842                         // ensure all function return values have a name - use the name of the function to disambiguate (this also provides a nice bit of help for debugging)
    843                         // ensure other return values have a name
     842                        // ensure all function return values have a name - use the name of the function to disambiguate (this also provides a nice bit of help for debugging).
     843                        // ensure other return values have a name.
    844844                        DeclarationWithType * ret = retVals.front();
    845845                        if ( ret->get_name() == "" ) {
  • src/SynTree/TypeDecl.cc

    r6f95000 r395fc37  
    2525
    2626std::string TypeDecl::typeString() const {
    27         static const char *kindNames[] = { "type", "incomplete type", "function type", "tuple type" };
    28         return kindNames[ kind ];
     27        static const std::string kindNames[] = { "type", "incomplete type", "function type", "tuple type" };
     28        return (kind != Any && isComplete() ? "sized " : "") + kindNames[ kind ];
    2929}
    3030
  • src/tests/.expect/tuplePolymorphism.txt

    r6f95000 r395fc37  
    33123 999.123 456
    44246 1998.25 912
     51.21 x 10.21 1111 v 54385938 1111 v 54385938
  • src/tests/memberCtors.c

    r6f95000 r395fc37  
    3030  WrappedInt x, y, z;
    3131};
     32
     33void ?{}(A * a) {
     34  // currently must define default ctor, since there's no "= default" syntax
     35}
    3236
    3337void ?{}(A * a, int x) {
  • src/tests/tuplePolymorphism.c

    r6f95000 r395fc37  
    1414//
    1515
     16// packed is needed so that structs are not passed with the same alignment as function arguments
     17__attribute__((packed)) struct A {
     18  double x;
     19  char y;
     20  double z;
     21};
     22
     23__attribute__((packed)) struct B {
     24  long long x;
     25  char y;
     26  long long z;
     27};
     28
     29// ensure that f is a viable candidate for g, even though its parameter structure does not exactly match
     30[A] f([A, B] x, B y) { printf("%g %c %g %lld %c %lld %lld %c %lld\n", x.0.[x,y,z], x.1.[x,y,z], y.[x,y,z]); return x.0; }
     31forall(otype T, otype U | { T f(T, U, U); })
     32void g(T x, U y) { f(x, y, y); }
     33
     34// add two triples
    1635forall(otype T | { T ?+?(T, T); })
    1736[T, T, T] ?+?([T, T, T] x, [T, T, T] y) {
     
    4059  [x1, x2, x3] = zzz+zzz;
    4160  printf("%d %g %d\n", x1, x2, x3);
     61
     62  // ensure non-matching assertions are specialized correctly
     63  g((A){ 1.21, 'x', 10.21}, (B){ 1111LL, 'v', 54385938LL });
    4264}
    4365
Note: See TracChangeset for help on using the changeset viewer.