Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.cc

    re3e16bc rbe9288a  
    1313// Update Count     : 62
    1414//
    15 
    1615#include "Autogen.h"
    1716
    1817#include <cstddef>                 // for NULL
    1918#include <algorithm>               // for count_if
    20 #include <cassert>                 // for strict_dynamic_cast, assert, assertf
     19#include <cassert>                 // for safe_dynamic_cast, assert, assertf
    2120#include <iterator>                // for back_insert_iterator, back_inserter
    2221#include <list>                    // for list, _List_iterator, list<>::iter...
     
    2524#include <vector>                  // for vector
    2625
    27 #include "AddVisit.h"              // for addVisit
    28 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    29 #include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
    30 #include "Common/utility.h"        // for cloneAll, operator+
    31 #include "GenPoly/DeclMutator.h"   // for DeclMutator
    32 #include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
    33 #include "SymTab/Mangler.h"        // for Mangler
    34 #include "SynTree/Attribute.h"     // For Attribute
    35 #include "SynTree/Mutator.h"       // for maybeMutate
    36 #include "SynTree/Statement.h"     // for CompoundStmt, ReturnStmt, ExprStmt
    37 #include "SynTree/Type.h"          // for FunctionType, Type, TypeInstType
    38 #include "SynTree/Visitor.h"       // for maybeAccept, Visitor, acceptAll
    39 
    40 class Attribute;
     26#include "AddVisit.h"             // for addVisit
     27#include "Common/ScopedMap.h"     // for ScopedMap
     28#include "GenPoly/DeclMutator.h"  // for DeclMutator
     29#include "GenPoly/ScopedSet.h"    // for ScopedSet
     30#include "Parser/LinkageSpec.h"   // for AutoGen, Intrinsic, Spec
     31#include "SymTab/Mangler.h"       // for mangleType
     32#include "SynTree/Statement.h"    // for SwitchStmt (ptr only), CompoundStmt
     33#include "SynTree/Type.h"         // for Type, ArrayType, Type::StorageClasses
     34#include "SynTree/Visitor.h"      // for Visitor
    4135
    4236namespace SymTab {
     
    136130        FunctionType * genDefaultType( Type * paramType ) {
    137131                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    138                 ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
     132                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new PointerType( Type::Qualifiers(), paramType->clone() ), nullptr );
    139133                ftype->get_parameters().push_back( dstParam );
    140134
     
    156150                ftype->get_returnVals().push_back( returnVal );
    157151                return ftype;
     152        }
     153
     154        /// true if the aggregate's layout is dynamic
     155        template< typename AggrDecl >
     156        bool hasDynamicLayout( AggrDecl * aggregateDecl ) {
     157                for ( TypeDecl * param : aggregateDecl->get_parameters() ) {
     158                        if ( param->isComplete() ) return true;
     159                }
     160                return false;
    158161        }
    159162
     
    178181                        FunctionType * ftype = funcDecl->get_functionType();
    179182                        assert( ! ftype->get_parameters().empty() );
    180                         Type * t = InitTweak::getPointerBase( ftype->get_parameters().front()->get_type() );
    181                         assert( t );
     183                        Type * t = safe_dynamic_cast< PointerType * >( ftype->get_parameters().front()->get_type() )->get_base();
    182184                        map.insert( Mangler::mangleType( t ), true );
    183185                }
     
    225227                        FunctionType * ftype = data.genType( refType );
    226228
    227                         if(concurrent_type && CodeGen::isDestructor( data.fname )) {
     229                        if(concurrent_type && InitTweak::isDestructor( data.fname )) {
    228230                                ftype->get_parameters().front()->get_type()->set_mutex( true );
    229231                        }
     
    250252                // parameters) are using in the variable exprs
    251253                assert( ftype->get_parameters().size() == 2 );
    252                 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    253                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
     254                ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
     255                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    254256
    255257                VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
     
    277279                FunctionType *copyCtorType = genCopyType( refType->clone() );
    278280
    279                 // add unused attribute to parameters of default constructor and destructor
    280                 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    281                 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    282 
    283281                // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
    284282                // right now these cases work, but that might change.
     
    303301
    304302        /// generates a single struct member operation (constructor call, destructor call, assignment call)
    305         void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true ) {
     303        void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
     304                ObjectDecl * returnVal = NULL;
     305                if ( ! func->get_functionType()->get_returnVals().empty() ) {
     306                        returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
     307                }
     308
    306309                InitTweak::InitExpander srcParam( src );
    307310
    308                 // assign to destination
    309                 Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), strict_dynamic_cast< ReferenceType* >( dstParam->get_type() )->get_base()->clone() ) );
     311                // assign to destination (and return value if generic)
     312                UntypedExpr *derefExpr = UntypedExpr::createDeref( new VariableExpr( dstParam ) );
     313                Expression *dstselect = new MemberExpr( field, derefExpr );
    310314                genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
     315
     316                if ( isDynamicLayout && returnVal ) {
     317                        // xxx - there used to be a dereference on returnVal, but this seems to have been wrong?
     318                        Expression *retselect = new MemberExpr( field, new VariableExpr( returnVal ) );
     319                        genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
     320                } // if
    311321        }
    312322
    313323        /// 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
    314324        template<typename Iterator>
    315         void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true ) {
     325        void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout, bool forward = true ) {
    316326                for ( ; member != end; ++member ) {
    317327                        if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
     
    349359
    350360                                Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
    351                                 makeStructMemberOp( dstParam, srcselect, field, func, forward );
     361                                makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout, forward );
    352362                        } // if
    353363                } // for
     
    357367        /// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
    358368        template<typename Iterator>
    359         void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {
     369        void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, bool isDynamicLayout ) {
    360370                FunctionType * ftype = func->get_functionType();
    361371                std::list<DeclarationWithType*> & params = ftype->get_parameters();
     
    383393                                        // matching parameter, initialize field with copy ctor
    384394                                        Expression *srcselect = new VariableExpr(*parameter);
    385                                         makeStructMemberOp( dstParam, srcselect, field, func );
     395                                        makeStructMemberOp( dstParam, srcselect, field, func, isDynamicLayout );
    386396                                        ++parameter;
    387397                                } else {
    388398                                        // no matching parameter, initialize field with default ctor
    389                                         makeStructMemberOp( dstParam, NULL, field, func );
     399                                        makeStructMemberOp( dstParam, NULL, field, func, isDynamicLayout );
    390400                                }
    391401                        }
     
    403413                // Make function polymorphic in same parameters as generic struct, if applicable
    404414                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
     415                bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
    405416
    406417                // generate each of the functions based on the supplied FuncData objects
     
    412423
    413424                // field ctors are only generated if default constructor and copy constructor are both generated
    414                 unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
     425                unsigned numCtors = std::count_if( newFuncs.begin(), newFuncs.end(), [](FunctionDecl * dcl) { return InitTweak::isConstructor( dcl->get_name() ); } );
    415426
    416427                if ( functionNesting == 0 ) {
     
    427438                        // generate appropriate calls to member ctor, assignment
    428439                        // destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
    429                         if ( ! CodeGen::isDestructor( dcl->get_name() ) ) {
    430                                 makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl );
     440                        if ( ! InitTweak::isDestructor( dcl->get_name() ) ) {
     441                                makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), dcl, isDynamicLayout );
    431442                        } else {
    432                                 makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, false );
    433                         }
    434                         if ( CodeGen::isAssignment( dcl->get_name() ) ) {
     443                                makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dcl, isDynamicLayout, false );
     444                        }
     445                        if ( InitTweak::isAssignment( dcl->get_name() ) ) {
    435446                                // assignment needs to return a value
    436447                                FunctionType * assignType = dcl->get_functionType();
    437448                                assert( assignType->get_parameters().size() == 2 );
    438                                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() );
     449                                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( assignType->get_parameters().back() );
    439450                                dcl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    440451                        }
     
    461472                                        // our inheritance model. I think the correct way to handle this is to
    462473                                        // cast the structure to the type of the member and let the resolver
    463                                         // figure out whether it's valid/choose the correct unnamed member
     474                                        // figure out whether it's valid and have a pass afterwards that fixes
     475                                        // the assignment to use pointer arithmetic with the offset of the
     476                                        // member, much like how generic type members are handled.
    464477                                        continue;
    465478                                }
    466479                                memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), Type::StorageClasses(), LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
    467480                                FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    468                                 makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor );
     481                                makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, isDynamicLayout );
    469482                                declsToAdd.push_back( ctor );
    470483                        }
     
    477490        void makeUnionFieldsAssignment( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
    478491                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    479                 copy->get_args().push_back( new AddressExpr( new VariableExpr( dstParam ) ) );
     492                copy->get_args().push_back( new VariableExpr( dstParam ) );
    480493                copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
    481494                copy->get_args().push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
     
    487500                FunctionType * ftype = funcDecl->get_functionType();
    488501                assert( ftype->get_parameters().size() == 2 );
    489                 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    490                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
     502                ObjectDecl * dstParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
     503                ObjectDecl * srcParam = safe_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
     504                ObjectDecl * returnVal = nullptr;
     505                if ( ! ftype->get_returnVals().empty() ) {
     506                        returnVal = safe_dynamic_cast< ObjectDecl * >( ftype->get_returnVals().front() );
     507                }
    491508
    492509                makeUnionFieldsAssignment( srcParam, dstParam, back_inserter( funcDecl->get_statements()->get_kids() ) );
    493                 if ( CodeGen::isAssignment( funcDecl->get_name() ) ) {
    494                         // also generate return statement in assignment
     510                if ( returnVal ) {
    495511                        funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    496512                }
     
    519535                cloneAll( typeParams, copyCtorType->get_forall() );
    520536                cloneAll( typeParams, assignType->get_forall() );
    521 
    522                 // add unused attribute to parameters of default constructor and destructor
    523                 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    524                 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    525537
    526538                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     
    700712
    701713        Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) {
    702                 tupleType = strict_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );
     714                tupleType = safe_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );
    703715                std::string mangleName = SymTab::Mangler::mangleType( tupleType );
    704716                if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;
     
    768780        CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) {
    769781                seenTuples.beginScope();
    770                 compoundStmt = strict_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );
     782                compoundStmt = safe_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );
    771783                seenTuples.endScope();
    772784                return compoundStmt;
Note: See TracChangeset for help on using the changeset viewer.