Changeset 18ca28e


Ignore:
Timestamp:
Oct 19, 2017, 11:15:19 AM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
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:
d411426d
Parents:
0a267c1
git-author:
Rob Schluntz <rschlunt@…> (10/13/17 13:49:10)
git-committer:
Rob Schluntz <rschlunt@…> (10/19/17 11:15:19)
Message:

Refactor autogen for EnumDecl? [fixes #47]

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r0a267c1 r18ca28e  
    128128                if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
    129129                        // explicitly construct the return value using the return expression and the retVal object
    130                         assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
     130                        assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() );
    131131
    132132                        ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() );
     
    138138
    139139                        // return the retVal object
    140                         returnStmt->set_expr( new VariableExpr( returnVals.front() ) );
     140                        returnStmt->expr = new VariableExpr( returnVals.front() );
    141141                } // if
    142142        }
  • src/SymTab/Autogen.cc

    r0a267c1 r18ca28e  
    174174        };
    175175
     176        class EnumFuncGenerator : public FuncGenerator {
     177        public:
     178                EnumFuncGenerator( EnumInstType * refType, const std::vector< FuncData > & data,  unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ) {}
     179
     180                virtual bool shouldAutogen() const override;
     181                virtual bool isConcurrentType() const override;
     182
     183                virtual void genFuncBody( FunctionDecl * dcl ) override;
     184                virtual void genFieldCtors() override;
     185
     186        private:
     187        };
     188
    176189        class TypeFuncGenerator : public FuncGenerator {
    177190                TypeDecl * typeDecl;
     
    247260                decl->fixUniqueId();
    248261                return decl;
    249         }
    250 
    251         /// generates a single enumeration assignment expression
    252         ApplicationExpr * genEnumAssign( FunctionType * ftype, FunctionDecl * assignDecl ) {
    253                 // enum copy construct and assignment is just C-style assignment.
    254                 // this looks like a bad recursive call, but code gen will turn it into
    255                 // a C-style assignment.
    256                 // This happens before function pointer type conversion, so need to do it manually here
    257                 // NOTE: ftype is not necessarily the functionType belonging to assignDecl - ftype is the
    258                 // type of the function that this expression is being generated for (so that the correct
    259                 // parameters) are using in the variable exprs
    260                 assert( ftype->get_parameters().size() == 2 );
    261                 ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().front() );
    262                 ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->get_parameters().back() );
    263 
    264                 VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
    265                 Type * assignVarExprType = assignVarExpr->get_result();
    266                 assignVarExprType = new PointerType( Type::Qualifiers(), assignVarExprType );
    267                 assignVarExpr->set_result( assignVarExprType );
    268                 ApplicationExpr * assignExpr = new ApplicationExpr( assignVarExpr );
    269                 assignExpr->get_args().push_back( new VariableExpr( dstParam ) );
    270                 assignExpr->get_args().push_back( new VariableExpr( srcParam ) );
    271                 return assignExpr;
    272         }
    273 
    274         // E ?=?(E volatile*, int),
    275         //   ?=?(E _Atomic volatile*, int);
    276         void makeEnumFunctions( EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd, SymTab::Indexer & indexer ) {
    277 
    278                 // T ?=?(E *, E);
    279                 FunctionType *assignType = genAssignType( refType );
    280 
    281                 // void ?{}(E *); void ^?{}(E *);
    282                 FunctionType * ctorType = genDefaultType( refType->clone() );
    283                 FunctionType * dtorType = genDefaultType( refType->clone() );
    284 
    285                 // void ?{}(E *, E);
    286                 FunctionType *copyCtorType = genCopyType( refType->clone() );
    287 
    288                 // add unused attribute to parameters of default constructor and destructor
    289                 ctorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    290                 dtorType->get_parameters().front()->get_attributes().push_back( new Attribute( "unused" ) );
    291 
    292                 // xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
    293                 // right now these cases work, but that might change.
    294 
    295                 // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
    296                 // Really they're something of a cross between instrinsic and autogen, so should
    297                 // probably make a new linkage type
    298                 FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting, true );
    299                 FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting, true );
    300                 FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting, true );
    301                 FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting, true );
    302 
    303                 // body is either return stmt or expr stmt
    304                 assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, genEnumAssign( assignType, assignDecl ) ) );
    305                 copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, genEnumAssign( copyCtorType, assignDecl ) ) );
    306 
    307                 declsToAdd.push_back( ctorDecl );
    308                 declsToAdd.push_back( copyCtorDecl );
    309                 declsToAdd.push_back( dtorDecl );
    310                 declsToAdd.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
    311 
    312                 indexer.addId( ctorDecl );
    313                 indexer.addId( copyCtorDecl );
    314                 indexer.addId( dtorDecl );
    315                 indexer.addId( assignDecl );
    316262        }
    317263
     
    586532        }
    587533
     534        void EnumFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) {
     535                // xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
     536                // Really they're something of a cross between instrinsic and autogen, so should
     537                // probably make a new linkage type
     538                funcDecl->linkage = LinkageSpec::Intrinsic;
     539                FunctionType * ftype = funcDecl->type;
     540                if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) {
     541                        assert( ftype->parameters.size() == 2 );
     542                        ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
     543                        ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() );
     544
     545                        // enum copy construct and assignment is just C-style assignment.
     546                        // this looks like a bad recursive call, but code gen will turn it into
     547                        // a C-style assignment.
     548                        // This happens before function pointer type conversion, so need to do it manually here
     549                        ApplicationExpr * callExpr = new ApplicationExpr( VariableExpr::functionPointer( funcDecl ) );
     550                        callExpr->get_args().push_back( new VariableExpr( dstParam ) );
     551                        callExpr->get_args().push_back( new VariableExpr( srcParam ) );
     552                        funcDecl->statements->push_back( new ExprStmt( noLabels, callExpr ) );
     553                        if ( CodeGen::isAssignment( funcDecl->name ) ) {
     554                                // also generate return statement in assignment
     555                                funcDecl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
     556                        }
     557                } else {
     558                        // default ctor/dtor body is empty - add unused attribute to parameter to silence warnings
     559                        assert( ftype->parameters.size() == 1 );
     560                        ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
     561                        dstParam->attributes.push_back( new Attribute( "unused" ) );
     562                }
     563        }
     564
     565        bool EnumFuncGenerator::shouldAutogen() const { return true; }
     566        bool EnumFuncGenerator::isConcurrentType() const { return false; }
     567        // enums do not have field constructors
     568        void EnumFuncGenerator::genFieldCtors() {}
     569
    588570        bool TypeFuncGenerator::shouldAutogen() const { return true; };
    589571
     
    611593
    612594        // opaque types do not have field constructors
    613         void TypeFuncGenerator::genFieldCtors() { return; };
     595        void TypeFuncGenerator::genFieldCtors() {};
    614596
    615597        //=============================================================================================
     
    628610                // must visit children (enum constants) to add them to the indexer
    629611                if ( enumDecl->has_body() ) {
    630                         EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
    631                         enumInst->set_baseEnum( enumDecl );
    632                         makeEnumFunctions( enumInst, functionNesting, declsToAddAfter, indexer );
     612                        EnumInstType enumInst( Type::Qualifiers(), enumDecl->get_name() );
     613                        enumInst.set_baseEnum( enumDecl );
     614                        EnumFuncGenerator gen( &enumInst, data, functionNesting, indexer );
     615                        generateFunctions( gen, declsToAddAfter );
    633616                }
    634617        }
Note: See TracChangeset for help on using the changeset viewer.