Changeset 9d7b3ea for src/GenPoly


Ignore:
Timestamp:
Mar 3, 2016, 1:28:51 PM (9 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, with_gc
Children:
36ebd03
Parents:
dbd8652
Message:

First draft of layout function builders

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/GenPoly/Box.cc

    rdbd8652 r9d7b3ea  
    2222
    2323#include "Box.h"
     24#include "DeclMutator.h"
    2425#include "InstantiateGeneric.h"
    2526#include "PolyMutator.h"
     
    5455                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
    5556
     57                /// Adds layout-generation functions to polymorphic types
     58                class LayoutFunctionBuilder : public DeclMutator {
     59                        unsigned int functionNesting;  // current level of nested functions
     60                public:
     61                        LayoutFunctionBuilder() : functionNesting( 0 ) {}
     62
     63                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
     64                        virtual Declaration *mutate( StructDecl *structDecl );
     65                        virtual Declaration *mutate( UnionDecl *unionDecl );
     66                };
     67               
    5668                /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
    5769                class Pass1 : public PolyMutator {
     
    159171        } // anonymous namespace
    160172
    161         void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) {
    162                 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    163                         if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) {
    164                                 (*i)->print( os );
    165                                 os << std::endl;
    166                         } // if
    167                 } // for
    168         }
    169 
    170173        /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
    171174        template< typename MutatorType >
     
    195198
    196199        void box( std::list< Declaration *>& translationUnit ) {
     200                LayoutFunctionBuilder layoutBuilder;
    197201                Pass1 pass1;
    198202                Pass2 pass2;
    199203                MemberExprFixer memberFixer;
    200204                Pass3 pass3;
     205                layoutBuilder.mutateDeclarationList( translationUnit );
    201206                mutateTranslationUnit/*All*/( translationUnit, pass1 );
    202207                mutateTranslationUnit/*All*/( translationUnit, pass2 );
     
    206211        }
    207212
     213        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
     214
     215        DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
     216                functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
     217                mutateAll( functionDecl->get_oldDecls(), *this );
     218                ++functionNesting;
     219                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     220                --functionNesting;
     221                return functionDecl;
     222        }
     223       
     224        /// Get a list of type declarations that will affect a layout function
     225        std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
     226                std::list< TypeDecl * > otypeDecls;
     227
     228                for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     229                        if ( decl->get_kind() == TypeDecl::Any ) {
     230                                otypeDecls.push_back( *decl );
     231                        }
     232                }
     233               
     234                return otypeDecls;
     235        }
     236
     237        /// Adds parameters for otype layout to a function type
     238        void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
     239                BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     240               
     241                for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     242                        layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( (*param)->get_base() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     243                }
     244        }
     245
     246        /// Builds a layout function declaration
     247        FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) {
     248                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     249                // because each unit generates copies of the default routines for each aggregate.
     250                FunctionDecl *layoutDecl = new FunctionDecl(
     251                        "__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
     252                layoutDecl->fixUniqueId();
     253                return layoutDecl;
     254        }
     255
     256        /// Makes a unary operation
     257        Expression *makeOp( const std::string &name, Expression *arg ) {
     258                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     259                expr->get_args().push_back( arg );
     260                return expr;
     261        }
     262
     263        /// Makes a binary operation
     264        Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
     265                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     266                expr->get_args().push_back( lhs );
     267                expr->get_args().push_back( rhs );
     268                return expr;
     269        }
     270
     271        /// Returns the dereference of a local pointer variable
     272        Expression *derefVar( ObjectDecl *var ) {
     273                return makeOp( "*?", new VariableExpr( var ) );
     274        }
     275
     276        /// makes an if-statement with a single-expression if-block and no then block
     277        Statement *makeCond( Expression *cond, Expression *ifPart ) {
     278                return new IfStmt( noLabels, cond, new ExprStmt( ifPart ), 0 );
     279        }
     280
     281        /// makes a statement that assigns rhs to lhs if lhs < rhs
     282        Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
     283                return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
     284        }
     285
     286        /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
     287        Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
     288                // check that the lhs is zeroed out to the level of rhs
     289                Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );
     290                // if not aligned, increment to alignment
     291                Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
     292                return makeCond( ifCond, ifExpr );
     293        }
     294       
     295        /// adds an expression to a compound statement
     296        void addExpr( CompoundStmt *stmts, Expression *expr ) {
     297                stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
     298        }
     299
     300        /// adds a statement to a compound statement
     301        void addStmt( CompoundStmt *stmts, Statement *stmt ) {
     302                stmts->get_kids().push_back( stmt );
     303        }
     304       
     305        virtual Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
     306                // do not generate layout function for "empty" tag structs
     307                if ( structDecl->get_members().empty() ) return structDecl;
     308
     309                // get parameters that can change layout, exiting early if none
     310                std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
     311                if ( otypeParams.empty() ) return structDecl;
     312
     313                // build layout function signature
     314                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     315                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     316                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     317               
     318                ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     319                layoutFnType->get_parameters().push_back( sizeParam );
     320                ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     321                layoutFnType->get_parameters().push_back( alignParam );
     322                ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     323                layoutFnType->get_parameters().push_back( offsetParam );
     324                addOtypeParams( layoutFnType, otypeParams );
     325
     326                // build function decl
     327                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType );
     328
     329                // calculate struct layout in function body
     330
     331                // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size
     332                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );
     333                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     334                unsigned long n_members = 0;
     335                bool firstMember = true;
     336                for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {
     337                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     338                        assert( dwt );
     339
     340                        if ( firstMember ) {
     341                                firstMember = false;
     342                        } else {
     343                                // make sure all members after the first (automatically aligned at 0) are properly padded for alignment
     344                                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( dwt->get_type() ) ) );
     345                        }
     346                       
     347                        // place current size in the current offset index
     348                        addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),
     349                                                                              derefVar( sizeParam ) ) );
     350                        ++n_members;
     351
     352                        // add member size to current size
     353                        addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( dwt->get_type() ) ) );
     354                       
     355                        // take max of member alignment and global alignment
     356                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( dwt->get_type() ) ) );
     357                }
     358                // make sure the type is end-padded to a multiple of its alignment
     359                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     360
     361                addDeclarationAfter( layoutDecl );
     362                return structDecl;
     363        }
     364       
     365        virtual Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
     366                // do not generate layout function for "empty" tag unions
     367                if ( unionDecl->get_members().empty() ) return unionDecl;
     368               
     369                // get parameters that can change layout, exiting early if none
     370                std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
     371                if ( otypeParams.empty() ) return unionDecl;
     372
     373                // build layout function signature
     374                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     375                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     376                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     377               
     378                ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     379                layoutFnType->get_parameters().push_back( sizeParam );
     380                ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     381                layoutFnType->get_parameters().push_back( alignParam );
     382                addOtypeParams( layoutFnType, otypeParams );
     383
     384                // build function decl
     385                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType );
     386
     387                // calculate union layout in function body
     388                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     389                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     390                for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
     391                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     392                        assert( dwt );
     393                       
     394                        // take max member size and global size
     395                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( dwt->get_type() ) ) );
     396                       
     397                        // take max of member alignment and global alignment
     398                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( dwt->get_type() ) ) );
     399                }
     400                // make sure the type is end-padded to a multiple of its alignment
     401                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     402
     403                addDeclarationAfter( layoutDecl );
     404                return unionDecl;
     405        }
     406       
    208407        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
    209408
Note: See TracChangeset for help on using the changeset viewer.